Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/asp.net-mvc-3/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
MVC3/JSON:当通过DataContract重命名属性名时,如何使用模型绑定?_Json_Asp.net Mvc 3_Datacontract - Fatal编程技术网

MVC3/JSON:当通过DataContract重命名属性名时,如何使用模型绑定?

MVC3/JSON:当通过DataContract重命名属性名时,如何使用模型绑定?,json,asp.net-mvc-3,datacontract,Json,Asp.net Mvc 3,Datacontract,在向客户机发送数据时,我使用为模型数据创建JsonResult。我的模型表示要在数据表中显示的数据,我希望仅在JSON中更改模型属性的名称,以便通过线路为每个数据表行发送不太详细的属性名称。现在,我试图通过JSON将数据表单元格值发送到服务器的控制器操作方法。返回的字段名称仍然是短名称,模型绑定似乎不喜欢这样。如何使模型绑定工作并保持通过JSON发送备用属性名的能力 型号: [DataContract()] public class UsageListModel { [DataMemb

在向客户机发送数据时,我使用为模型数据创建JsonResult。我的模型表示要在数据表中显示的数据,我希望仅在JSON中更改模型属性的名称,以便通过线路为每个数据表行发送不太详细的属性名称。现在,我试图通过JSON将数据表单元格值发送到服务器的控制器操作方法。返回的字段名称仍然是短名称,模型绑定似乎不喜欢这样。如何使模型绑定工作并保持通过JSON发送备用属性名的能力

型号:

[DataContract()]
public class UsageListModel {

    [DataMember(Name = "results")]
    public IEnumerable<UsageModel> Usages { get; set; }
}

[DataContract()]
public class UsageModel {

    [DataMember(Name = "job")]
    public string JobId { get; set; }

    [DataMember(Name = "dt")]
    public DateTime UsageDate { get; set; }

    [DataMember(Name = "qty")]
    public int Quantity { get; set; }

    [DataMember(Name = "uom")]
    public string UnitOfMeasure { get; set; }

    [DataMember(Name = "nts")]
    public string Notes { get; set; }
}
[DataContract()]
公共类UsageListModel{
[DataMember(Name=“results”)]
公共IEnumerable用法{get;set;}
}
[DataContract()]
公共类使用模型{
[DataMember(Name=“job”)]
公共字符串JobId{get;set;}
[数据成员(Name=“dt”)]
public DateTime UsageDate{get;set;}
[数据成员(Name=“数量”)]
公共整数数量{get;set;}
[数据成员(Name=“uom”)]
公共字符串度量单位{get;set;}
[DataMember(Name=“nts”)]
公共字符串注释{get;set;}
}

我仍然不相信MVC没有提供一些更简单的方法来使用自定义属性(甚至.NET数据契约属性)进行绑定。考虑到它不。。。最好的办法是实现自己的IModelBinder。使用反射获取属性的DataMember名称,并在绑定上下文中查找这些值

下面是关于模型绑定的一个很好的参考:

维护自定义活页夹的良好通用方法:

编辑

处理已定义类型的泛型模型绑定器。要将其添加到应用程序中,请在global.asax中添加此行:

ModelBinders.Binders.Add(typeof(UsageModel), new CustomModelBinder<UsageModel>());
ModelBinders.Binders.Add(typeof(UsageModel),newcustommodelbinder());
以及活页夹:

public class CustomModelBinder<T> : IModelBinder
{
    public override bool IsMatch(Type t)
    {
        return t == typeof(T);
    }

    public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        Type t = typeof(T);
        var entity = (bindingContext.Model ?? Activator.CreateInstance(t));

        // Cycle through the properties and assign values.
        foreach (PropertyInfo p in t.GetProperties())
        {
            string sourceKey;

            // this is what you'd do if you wanted to bind to the property name
            // string sourceKey = p.Name;

            // TODO bind sourceKey to the name in attribute DataMember

            Type propertyType = p.PropertyType;

            // now try to get the value from the context ...
            ValueProviderResult valueResult = bindingContext.ValueProvider.GetValue(sourceKey);
            if (valueResult != null)
            {
                bindingContext.ModelState.SetModelValue(sourceKey, valueResult);
                p.SetValue(entity, valueResult.ConvertTo(propertyType), null);
            }
        }
        return entity;
    }
}
公共类CustomModelBinder:IModelBinder
{
公共覆盖布尔IsMatch(t型)
{
返回t==typeof(t);
}
公共重写对象BindModel(ControllerContext ControllerContext,ModelBindingContext bindingContext)
{
类型t=类型(t);
var entity=(bindingContext.Model??Activator.CreateInstance(t));
//循环浏览属性并指定值。
foreach(t.GetProperties()中的PropertyInfo p)
{
字符串源键;
//如果您想绑定到属性名,您会这样做
//字符串sourceKey=p.Name;
//TODO将sourceKey绑定到属性DataMember中的名称
类型propertyType=p.propertyType;
//现在尝试从上下文中获取值。。。
ValueProviderResult valueResult=bindingContext.ValueProvider.GetValue(sourceKey);
if(valueResult!=null)
{
bindingContext.ModelState.SetModelValue(sourceKey,valueResult);
p、 SetValue(实体,valueResult.ConvertTo(propertyType),null);
}
}
返回实体;
}
}

它没有那么优雅,但我通常通过创建一个中间类(我称之为ViewModel)来实现这一点,该类具有这些短名称属性,并且可以在它和实际模型之间来回转换。尽管看起来工作很忙,但ViewModel在这段时间之外还是很有用的——例如,如果需要的话,您可以使用它轻松缓存客户端信息,或者对测试中客户端的内容进行序列化/反序列化。

我在浏览时偶然发现了这个问题的潜在答案

直到现在我才意识到这一点,但显然可以向方法参数添加属性。让我们举一个简单的例子:

public ActionResult SomeMethod(string val) {
    return View(val);
}
如果您调用这个URL--/MyController/SomeMethod?val=mytestval--那么您将在模型中返回“mytestval”,对吗?现在你可以写下:

public ActionResult SomeMethod([Bind(Prefix="alias")] string val) {
    return View(val);
}
现在,此URL将产生相同的结果:/MyController/somethod?alias=mytestval


无论如何,我仍然不确定这是否能回答您的问题,但我认为这很有趣。

这为我指明了正确的方向,但我很难想出如何实现最少的代码来实现这一点。乍一看,在我看来,创建一个从DefaultModelBinder继承的自定义模型绑定器类是一种可行的方法。经过大量搜索后,似乎覆盖DefaultModelBinder.GetTypeDescriptor也可以做到这一点(我可以在DataMember名称中替换属性名称),但现在我仍在讨论如何实现这一点。还是我走错了路?我应该实现IModelBinder吗?我想您应该实现IModelBinder来处理您的自定义类型,因为您希望其他模型的绑定保持不变。。。我会更新的。我无法让它工作。似乎没有处理数组索引,也没有处理子对象。我可以看到bindingContext包含“UsageInformation.results[0].job”、“UsageInformation.results[0].nts”等的值(ModelName=“UsageInformation”),但我无法找到将这些值放在sourceKey变量中的一般方法。而且,这个解决方案似乎忽略了任何模型验证。很抱歉,没有进行解释。然而,基于datacontract序列化程序为json对象构建一个严肃可靠的ModelBinder并非易事。特别是如果您希望支持所有数据注释。它可能离您正在实现的软件很远。此外,Mvc4 WebApi在其模型绑定器中使用DataContratSerializer,并且在处理日期方面存在严重问题……Microsoft承诺在最终版本中提供Json.Net序列化程序以解决这些问题。因此,在我看来,在DataContract模型绑定器的实现上浪费大量精力是不值得的