【问题标题】:MVC5 ViewModel properties null on HTTPPostHTTPPost 上的 MVC5 ViewModel 属性为空
【发布时间】:2016-03-24 18:42:49
【问题描述】:

我知道,以前有人问过这个问题,但我还没有找到答案,我的例子似乎比大多数简单得多。我确保模型数据在表单内,并确保 Post 操作与 Get 操作匹配;没有日期格式问题;我有类似的视图和控制器,我比较过它们工作得很好。此示例使用传统路由,但我也尝试过属性路由,但行为没有变化。我什至删除了 EditorFor ReportName 并将其放入 HiddenFor 中。隐藏的 ReportID 始终填充且正确,ReportName 和 ReportAbbr 始终为空。 :(

首先,这是我的视图模型:

namespace Core.AdminData
{
    [System.Runtime.Serialization.DataContract(Name = "MyReport")]
    public class MyReport
    {
        [System.Runtime.Serialization.DataMember(Name = "ReportID", Order = 0)]
        public int ReportID { get; set; }

        [System.Runtime.Serialization.DataMember(Name = "ReportName", Order = 1)]
        [Display(Name = "Name")]
        [Required(ErrorMessage = "Name Required")]
        public string ReportName { get; private set; }

        [System.Runtime.Serialization.DataMember(Name = "ReportAbbr", Order = 2)]
        [Display(Name = "Abbreviation")]
        [Required(ErrorMessage = "Abbreviation Required")]
        public string ReportAbbr { get; private set; }

        public MyReport()
        {
            ;
        }
    }
}

这是我的控制器:

public class ReportsController : Controller
{
    [HttpGet]
    public ActionResult TrendEdit(int id)
    {
        using (Client client = new Client(ConfigHelper.Protocol(), ConfigHelper.Host(), ConfigHelper.Port()))
        {
            MyReport rpt = null;
            try
            {
                rpt = client.GetReport(id);
                if (rpt == null)
                {
                    TempData["ErrorText"] = "Report does not exist";
                    return this.RedirectToAction("List");
                }
            }
            catch (Exception exc)
            {
                TempData["ErrorText"] = exc.Message;
                return this.RedirectToAction("List");
            }
            return View(rpt);
        }
    }

    [HttpPost]
    public ActionResult TrendEdit(MyReport report)
    {
        using (Client client = new Client(ConfigHelper.Protocol(), ConfigHelper.Host(), ConfigHelper.Port()))
        {
            try
            {
                if (!this.ModelState.IsValid || client.UpdateReport(report).StatusCode != SSStatus.Success)
                {
                    ViewBag.ErrorText = "An error occurred.  Please contact your web administrator for assistance.";
                    return View(report);
                }
            }
            catch (Exception exc)
            {
                ViewBag.ErrorText = exc.Message;
                return View(report);
            }
            return this.RedirectToAction("List");
        }
    }
}

最后,这是我的观点:

@using Core.AdminData
@model MyReport

@{
    ViewBag.Title = "Edit Report";
    Layout = "~/Views/Shared/_ContentLayout.cshtml";
}

<div class="panel panel-default">
    <div class="panel-heading hidden-xs">
        <h4>Edit Report</h4>
    </div>

    @using (Html.BeginForm())
    {
        @Html.HiddenFor(model => model.ReportID)

        <div class="container-fluid panel-body">
            <div class="row">
                <div class="col-xs-12 message-error">@ViewBag.ErrorText</div>
            </div>
            <div class="row">
                <div class="col-xs-4 col-md-3 custom-label">
                    @Html.LabelFor(model => model.ReportName)
                </div>
                <div class="col-xs-8 col-md-9 custom-field">
                    @Html.EditorFor(model => model.ReportName)
                </div>
            </div>
            <div class="row">
                <div class="col-xs-offset-4 col-xs-8 col-md-offset-3 col-md-9 message-error">
                    @Html.ValidationMessageFor(model => model.ReportName)
                </div>
            </div>
            <div class="row">
                <div class="col-xs-4 col-md-3 custom-label">
                    @Html.LabelFor(model => model.ReportAbbr)
                </div>
                <div class="col-xs-8 col-md-9 custom-field">
                    @Html.EditorFor(model => model.ReportAbbr)
                </div>
            </div>
            <div class="row">
                <div class="col-xs-offset-4 col-xs-8 col-md-offset-3 col-md-9 message-error">
                    @Html.ValidationMessageFor(model => model.ReportAbbr)
                </div>
            </div>
            <div class="row">
                <div class="col-xs-4 col-md-3 text-right">
                    <input type="submit" value="Save" class="btn btn-default btn-sm" />
                </div>
            </div>
        </div>
    }
</div>

如果我遗漏了任何有用的代码,请告诉我。我希望这是显而易见的。我宁愿有一个“Duh”的时刻,也不愿继续与这段代码作斗争。 ;) TIA!

【问题讨论】:

  • 另一个注意事项,如果有帮助,ReportName 和 ReportAbbr 的数据 ~are~ 在 Request.Form 中。只有 TrendEdit 帖子中的 report.ReportName 为空。

标签: asp.net-mvc asp.net-mvc-5 http-post model-binding


【解决方案1】:

您的ReportNameReportAbbr 属性具有私有设置器,因此DefaultModelBinder 无法设置值。将它们更改为具有公共设置器

public string ReportName { get; set; }
public string ReportAbbr { get; set; }

【讨论】:

  • 谢谢斯蒂芬!正如我所希望的那样——呃!这门课是由几个月前离开公司的人创建的,我刚刚接手。我一直在查看属性,认为某些元数据一定是错误的,并且完全错过了看到私有设置器。非常感谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-10-25
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多