MVC默认绑定器不绑定嵌套类

时间:2015-03-02 00:53:30

标签: c# asp.net-mvc model-binding

我无法获取MVC默认绑定器来序列化嵌套对象。 我做了很多研究,试图弄清楚我做错了什么,但我没有看到它。

该模型带有所有嵌套对象的创建(由构造函数提供,没有创建任何内容)但没有数据被序列化。

我已经覆盖了DefaultBinder并添加了断点以找出失败的原因。它似乎将Start和End视为DateTimePart,但不会对它们做任何事情。

我花了很多时间来阅读和理解DefaultBinder的逻辑,我读过的所有内容似乎都表明这应该有效,但事实并非如此。任何帮助或猜测都会受到赞赏,因为这让我疯狂。

另外,为了说清楚,我意识到我可以使用自定义活页夹来解决这个问题,但在此之前,我想了解为什么这不适用于默认活页夹。

这是控制器:

public class TestController : Controller
{
    // GET: Test
    public ActionResult Index()
    {
        StartEndTime se = new StartEndTime();
        se.Start = new DateTimeParts();
        se.End = new DateTimeParts();
        se.Start.Date = new DateTime(2015, 2, 22, 13, 12, 0);
        se.End.Date = new DateTime(2015, 3, 1, 10, 43, 0);
        return View(se);
    }

    [HttpPost]
    public ActionResult Index(StartEndTime se)
    {
        return RedirectToAction("Index");
    }
}

这里是视图(仅示例,复制问题,但真正的问题以不同方式处理时间和日期)

@model Models.StartEndTime

@using (Html.BeginForm())
{
    @Html.AntiForgeryToken()


    @Html.EditorFor(model => model.Start.DatePart)
    @Html.EditorFor(model => model.Start.TimePart)

    @Html.EditorFor(model => model.End.DatePart)
    @Html.EditorFor(model => model.End.TimePart)

    @Html.SButtonSave()
}

<div>
    @Html.ActionLink("Back to List", "Index")
</div>

生成的HTML的相关部分:

<input name="Start_DatePart" id="Start_DatePart" class="text-box single-line form-control datepicker" type="text" value="2015-02-22">
<input name="Start_TimePart" id="Start_TimePart" class="text-box single-line form-control datepicker" type="text" value="0001-01-01">
<input name="End_DatePart" id="End_DatePart" class="text-box single-line form-control datepicker" type="text" value="2015-03-01">
<input name="End_TimePart" id="End_TimePart" class="text-box single-line form-control datepicker" type="text" value="0001-01-01">

最后是模特。我已经包含了所有内容,因为我不确定是什么导致了这个问题:

public class DateTimeParts
{
    public DateTime? Date { get; set; }

    public DateTime? DatePart
    {
        get
        {
            if (Date.HasValue)
                return Date.Value.Date;
            else
                return null;
        }
        set
        {
            if (value.HasValue)
            {
                if (Date.HasValue)
                    Date = value.Value.Date.Date + Date.Value.TimeOfDay;
                else
                    Date = value.Value.Date.Date;
            }
            else
            {
                Date = null;
            }
        }
    }

    public DateTime? TimePart
    {
        get
        {
            if (Date.HasValue)
                return new DateTime() + Date.Value.TimeOfDay;
            else
                return null;
        }
        set
        {
            if (value.HasValue)
            {
                if (Date.HasValue)
                    Date = Date.Value.Date + value.Value.TimeOfDay;
                else
                    Date = new DateTime() + value.Value.TimeOfDay;
            }
            else
            {
                Date = new DateTime();
            }
        }
    }
}

public class StartEndTime
{
    public DateTimeParts Start { get; set; }

    public DateTimeParts End { get; set; }

    public int Minutes
    {
        get
        {
            if (!Start.Date.HasValue || !End.Date.HasValue)
                return 0;
            else
                return (int)(End.Date.Value - Start.Date.Value).TotalMinutes;
        }
        set
        {
            if (!Start.Date.HasValue)
                return;
            End.Date = Start.Date.Value + new TimeSpan(0, value, 0);
        }
    }
}

1 个答案:

答案 0 :(得分:0)

我敢打赌,这就是C#处理DateTime的方式。例如,0001-01-01看起来不像有效日期,而且它缺少时间戳。

您应该将value设置为:

string dateString = "5/1/2008 8:30:52 AM";

我认为默认的活页夹会接受它。使用@Html.HiddenFor对其进行测试。