4

The problem

At this point I have a problem where my Get action is trying to read a DateTime parameter in a diferent format that is sent.

While the DateTime sent has this format: 0:dd/MM/yyyy The Get Actions expects: 0:MM/dd/yyyy

The solution (maybe)

In order to change what the Get action is expecting I'm using a Custom Model Binding.

The GET Action

    public async Task<IActionResult> Details(int? id, [ModelBinder(typeof(PModelBinder))]DateTime date)

The ModelBinder class

Now here are a few things that are missing and I don't know how to complete it properly:

public class PModelBinder : IModelBinder
{
    public Task BindModelAsync(ModelBindingContext bindingContext)
    {
        string theDate = bindingContext.HttpContext.Request.QueryString["date"]; 
        //What should I write inside the []? 
        //I've tried QueryString["date"] which is the name of the parameter but it says is wrong
        DateTime dt = new DateTime();
        bool success = DateTime.TryParse(date); //Should I apply ParseExact? How should I do it?
        if (success)
        {
            return new //what should I be returning here? dt?
        }

    }
}

I've several questions marked as comments in the code above since I'm just starting to understand Custom Model Binding. Hope anyone can give me some advice.

I'm following this article:

https://weblogs.asp.net/melvynharbour/mvc-modelbinder-and-localization

But it's from 2008!!!, Although it seems valid since it's exactly the problem I'm having with my GET Action (diferent date formats)

Update: aditional information

The parameter date is defined as:

    [DisplayFormat(DataFormatString = "{0:dd/MM/yyyy}", ApplyFormatInEditMode = true)]
    public DateTime FechaLInicioLiq { get; set; }

and the URL build when calling that GET Action has this structure for the date parameter:

date=10%2F11%2F2017%200%3A00%3A00
3
  • Alberto You need to DateTime "0:MM/dd/yyyy" to "0:dd/MM/yyyy " .Am I correct ... Commented Nov 23, 2017 at 6:50
  • @VIGNESHARUNACHALAM The datetime is sent with this format: 0:dd/MM/yyyy, but the GET Action is trying to read the parameter as if it's format were 0:MM/dd/yyyy, thus generating an error. So I need that the GET Actions starts accepting the 0:dd/MM/yyyy format. Commented Nov 23, 2017 at 6:53
  • Suggest your look at the code in this article for core-mvc Commented Nov 23, 2017 at 7:00

1 Answer 1

6

You have several issues with your model binder implementation:

  1. Do not hardcode parameter name (date). Use bindingContext.ModelName instead.
  2. You should handle situation if value was not actually provided. You could check it by comparing result of IValueProvider.GetValue() with ValueProviderResult.None.

Here is sample DateTime model binder that accomplish what you need:

public class DateTimeModelBinder : IModelBinder
{
    private readonly IModelBinder baseBinder = new SimpleTypeModelBinder(typeof(DateTime));

    public Task BindModelAsync(ModelBindingContext bindingContext)
    {
        var valueProviderResult = bindingContext.ValueProvider.GetValue(bindingContext.ModelName);
        if (valueProviderResult != ValueProviderResult.None)
        {
            bindingContext.ModelState.SetModelValue(bindingContext.ModelName, valueProviderResult);

            var valueAsString = valueProviderResult.FirstValue;

            //  valueAsString will have a string value of your date, e.g. '31/12/2017'
            var dateTime = DateTime.ParseExact(valueAsString, "dd/MM/yyyy", CultureInfo.InvariantCulture);
            bindingContext.Result = ModelBindingResult.Success(dateTime);

            return Task.CompletedTask;
        }

        return baseBinder.BindModelAsync(bindingContext);
    }
}
Sign up to request clarification or add additional context in comments.

5 Comments

Thanks for the reply. I'm trying to implement it but I'm gettint an error claiming that the result of this line: bindingContext.ModelState.SetModelValue(bindingContext.ModelName, valueProvideResult); once is passed to the ParseExact function, that string was not recognized as a valid DateTime. I'm trying to debug it on that line to see the value but it skips that line and throw the error before I could see it.
i.imgur.com/otBzAWe.png It says that the result of SetModelValue, once is evaluated for the PArseExact function, is not considered a valid DateTime format ):
As far as your date string also contains time part (0:00:00) you should use following format for ParseExact(): DateTime.ParseExact(valueAsString, "dd/MM/yyyy h:m:s", CultureInfo.InvariantCulture)
Thank you very much! I was trying with 0:dd/MM/yyyy but it was not good enough. I don't think I would have dealt with this problem without your help! Thanks again!
working example but i would suggest nullable DateTime to return null if not binded

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.