简体   繁体   中英

Submission of a nullable datetime is null

How to save a TimeOfDay? [duplicate] haven't an answer and this present post it's about a specific problem an not a general question like that post

I'm trying save/submit a Date and a TimeOfDay of a specific DateTime (nullable) variable but when it arrives to my controller its value is always null even user insert other values. How can I solve this?

My visual objective:

在此处输入图片说明

My view:

<div style="display:inline-block">
            <div class="editor-label">
                Initial date:
            </div>
            <div class="editor-field">
                @Html.TextBoxFor(model => model.StartDate.Value.Date, new { type = "date" })
                @Html.ValidationMessageFor(model => model.StartDate)
            </div>
        </div>

        <div style="display:inline-block">
            <div class="editor-label">
                Initial hour:
            </div>
            <div class="editor-field">
                @Html.TextBoxFor(model => model.StartDate.Value.TimeOfDay, new { type = "time" })
                @Html.ValidationMessageFor(model => model.StartDate)
            </div>
        </div>

My model:

[DataType(DataType.Date), DisplayFormat(DataFormatString = "{0:dd/MM/yy}", ApplyFormatInEditMode = true)]
public DateTime? StartDate { get; set; }

My model binding (from this link what is great but don't work to nullable dates and I don't know why) :

public class DateTimeModelBinder : DefaultModelBinder
{
    private Nullable<T> GetA<T>(ModelBindingContext bindingContext, string key) where T : struct
    {
        if (bindingContext.ValueProvider.ContainsPrefix(bindingContext.ModelName))
        {
            if (string.IsNullOrEmpty(key)) key = bindingContext.ModelName;
            else key = bindingContext.ModelName + "." + key;
        }
        if (string.IsNullOrEmpty(key)) return null;

        ValueProviderResult value;

        value = bindingContext.ValueProvider.GetValue(key);
        bindingContext.ModelState.SetModelValue(key, value);

        if (value == null)
        {
            return null;
        }

        Nullable<T> retVal = null;
        try
        {
            retVal = (Nullable<T>)value.ConvertTo(typeof(T));
        }
        catch (Exception) { }

        return retVal;
    }

    public override object BindModel(
        ControllerContext controllerContext,
        ModelBindingContext bindingContext)
    {
        if (bindingContext == null) throw new ArgumentNullException("bindingContext");

        // Check for a simple DateTime value with no suffix
        DateTime? dateTimeAttempt = GetA<DateTime>(bindingContext, "");
        if (dateTimeAttempt != null)
        {
            return dateTimeAttempt.Value;
        }

        // Check for separate Date / Time fields
        DateTime? dateAttempt = GetA<DateTime>(bindingContext, "Date");
        DateTime? timeAttempt = GetA<DateTime>(bindingContext, "TimeOfDay");

        //If we got both parts, assemble them!
        if (dateAttempt != null && timeAttempt != null)
        {
            return new DateTime(dateAttempt.Value.Year,
                dateAttempt.Value.Month,
                dateAttempt.Value.Day,
                timeAttempt.Value.Hour,
                timeAttempt.Value.Minute,
                timeAttempt.Value.Second);
        }

        //Only got one half? Return as much as we have!
        return dateAttempt ?? timeAttempt;
    }
}

The binder is looking for two post values called StartDate.Date and StartDate.TimeOfDay ; however, the TextBoxFor method will have named these controls StartDate.Value.Date and StartDate.Value.TimeOfDay instead.

Try adding code to your binder to check for these names:

DateTime? dateAttempt = GetA<DateTime>(bindingContext, "Date");
DateTime? timeAttempt = GetA<DateTime>(bindingContext, "TimeOfDay");

if (dateAttempt == null && timeAttempt == null)
{
    dateAttempt = GetA<DateTime>(bindingContext, "Value.Date");
    timeAttempt = GetA<DateTime>(bindingContext, "Value.TimeOfDay");
}

The problem was the lack of one ? on the call of my ModelBinder on Global.asax . So its code changed to:

ModelBinders.Binders.Add(typeof(DateTime?), new Models.DateTimeModelBinder());

and the changes Richard Deeming suggests should be done too:

if (dateAttempt == null && timeAttempt == null)
{
    dateAttempt = GetA<DateTime>(bindingContext, "Value.Date");
    timeAttempt = GetA<DateTime>(bindingContext, "Value.TimeOfDay");
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM