4

在向客户端发送数据时,我使用DataContractJsonSerializer为我的模型数据创建 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; }
}
4

3 回答 3

2

它没有那么优雅,但我通常只通过创建一个具有这些短名称属性并且可以在它和实际模型之间来回转换的中间类(我将其称为 ViewModel)来做到这一点。虽然看起来工作很忙,但 ViewModel 可以在这段时间之外发挥作用——例如,如果需要,您可以使用它轻松缓存客户端信息,或者在测试中准确序列化/反序列化客户端的去往/来自客户端的内容。

于 2012-05-11T16:54:01.567 回答
0

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

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

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/SomeMethod?alias=mytestval。

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

于 2012-06-04T06:10:58.820 回答
0

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

这是关于模型绑定的一个很好的参考:http: //msdn.microsoft.com/en-us/magazine/hh781022.aspx

维护自定义活页夹的一个很好的通用方法:http: //lostechies.com/jimmybogard/2009/03/18/a-better-model-binder/

编辑

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

ModelBinders.Binders.Add(typeof(UsageModel), new CustomModelBinder<UsageModel>());

和粘合剂:

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;
    }
}
于 2012-05-03T07:16:58.660 回答