asp.net core custom model binder just for one property
Asked Answered
N

2

15

I have a simple model for my asp.net core controller:

[HttpPost]
public async Task<DefaultResponse> AddCourse([FromBody]CourseDto dto)
{
     var response = await _courseService.AddCourse(dto);
     return response;
}

My model is :

 public class CourseDto
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string Genre { get; set; }
    public string Duration { get; set; }
    public string Level { get; set; }
    public string AgeRange { get; set; }
    public string Notes { get; set; }
    public bool Active { get; set; }
    public string OrganisationCode { get; set; }
}

I'm trying to set value of "OrganisationCode" using a custom mode binder or action filter, but had no success. I would be thnakful if you advise whats the right way to updat ethe model before executing the action.

Thanks.

Ninety answered 2/7, 2017 at 12:41 Comment(1)
Please provide more information regarding the origin of the data you want to bind to OrganisationCode property. Is it posted alongside the rest of the properties with a different name?Cimbri
P
15

I will show you here a very simple custom model binder I have just written (and tested in .Net Core 2.0):

My model binder:

public class CustomModelBinder : IModelBinder
{
    public Task BindModelAsync(ModelBindingContext bindingContext)
    {
        var valueProviderResult = bindingContext.ValueProvider.GetValue(bindingContext.ModelName);
        var value = valueProviderResult.FirstValue; // get the value as string

        var model = value.Split(",");
        bindingContext.Result = ModelBindingResult.Success(model);

        return Task.CompletedTask;
    }
}

My model (and notice, only one property has my custom model binder annotation):

public class CreatePostViewModel
{
    [Display(Name = nameof(ContentText))]
    [MinLength(10, ErrorMessage = ValidationErrors.MinLength)]
    public string ContentText { get; set; }

    [BindProperty(BinderType = typeof(CustomModelBinder))]
    public IEnumerable<string> Categories { get; set; } // <<<<<< THIS IS WHAT YOU ARE INTERESTER IN

    #region View Data
    public string PageTitle { get; set; }
    public string TitlePlaceHolder { get; set; }
    #endregion
}

What it does is: it receives some text like "aaa,bbb,ccc", and converts it into array, and return it to the ViewModel.

I hope that helps.

DISCLAIMER: I am not an expert in model binders writing, I have learnt that 15 minutes ago, and I found your question (with no helpful answer), so I tried to help. This is a very basic model binder, some improvements are surely required. I learned how to write it from the official documentation page.

Prochora answered 18/4, 2018 at 22:33 Comment(2)
Have you rested that, that's not enough to get it to workMorrissey
@Morrissey I am pretty much that this code (even if it does not compile as it is literally), it can be pretty much helpful after reading a bit about the topic. I copied the code from one of the projects I worked on (of course totally written by me).Prochora
J
4

The [FromBody] attribute you are using on the action parameter. means that you direct the default behavior of Model Binding to use the formatters instead. That is why your custom Model Binder does not work.

And [FromBody] is reading the content (request body). So you won't get the request body from your Action Filter, as the request body is a non-rewindable stream, so it suppose to be read only once (I'm assuming that you are trying to read the request body from Action Filter).

My suggestion is to use your custom model binder and remove the FromBody Attribute.

Jaundiced answered 24/8, 2017 at 1:54 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.