在最近的一个项目中 - 我遇到了意想不到的障碍 具有简单公共字段的类(注意不是属性)似乎不希望与之相配 ASP.net MVC 3.0模型绑定器。
这是设计吗?
除了将字段更改为属性 - 这里有任何选项吗?
简单字段(而不是属性)的原因是因为我正在使用MVC和Script Sharp项目之间的共享库。脚本锐利支持属性 - 但它在视图中使用javascript变得混乱(使用knockout.js)
所以尽管我喜欢(只是使用属性)我在我的dto课程中使用公共字段。
我想避免对同一个类进行多次定义。叹息
答案 0 :(得分:12)
这是设计吗?
是的,只有具有公共getter / setter的属性才能使用默认的模型绑定器。
除了将字段更改为属性 - 这里有任何选项吗?
这就是你应该做的事情,因为你应该使用视图模型。视图模型专为视图而设计。因此,将字段更改为属性是正确的方法。现在,如果您不遵循良好实践并尝试将域模型用作操作的输入/输出,那么您将必须编写一个适用于字段的自定义模型绑定器。不过,这将是很多工作。
答案 1 :(得分:1)
我知道这违背了c#团队的理念,但我认为poco类中的字段很干净。对我来说似乎不那么动人的部分。无论如何,
这是一个将加载字段的模型绑定器。这是相当微不足道的。请注意,您可以使用Activator.CreateInsance
的新对象,也可以以现有对象作为起点。我使用是/否下拉菜单,你可能有复选框,在这种情况下,你不得不循环通过fieldinfos并寻找丢失的表单输入b / c html如果它是一个假复选框,则不提交表单项。
〜/ Binders / FieldModelBinder.cs
using System;
using System.Reflection;
using System.Web.Mvc;
namespace MyGreatWebsite.Binders
{
public class FieldModelBinder : DefaultModelBinder
{
public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
var obj = controllerContext.HttpContext.Session["CurrentObject"];// Activator.CreateInstance(bindingContext.ModelType);
var form = controllerContext.HttpContext.Request.Form;
foreach (string input in form)
{
FieldInfo fieldInfo = obj.GetType().GetField(input);
if (fieldInfo == null)
continue;
else if (fieldInfo.FieldType == typeof(bool))
fieldInfo.SetValue(obj, form[input] == "Yes");
else
fieldInfo.SetValue(obj, Convert.ChangeType(form[input], fieldInfo.FieldType));
}
return obj;
}
}
}
<强> Startup.cs 强>
public partial class Startup
{
public void Configuration(IAppBuilder app)
{
ConfigureAuth(app);
ModelBinders.Binders.Add(typeof(FieldModelBinder), new FieldModelBinder());
}
}
<强>用法强>
[HttpPost]
public ActionResult MyGreatAction([ModelBinder(typeof(FieldModelBinder))] MyGreatProject.MyGreatNamespace.MyGreatType instance, string myGreatParameters)
{
DoSomethingGreatWithMyInstance();
return View();
}