ASP.NET Custom Model Binding: DateTime

落爺英雄遲暮 提交于 2019-12-02 03:12:55

问题


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

回答1:


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);
    }
}


来源:https://stackoverflow.com/questions/47449015/asp-net-custom-model-binding-datetime

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!