ASP.. NET MVC 4属性重命名发布

本文关键字:重命名 属性 NET MVC ASP | 更新日期: 2023-09-27 18:04:44

给出了以下约定:每个Action都有一个类型为BaseRequest的参数,其数据取决于ActionViewModel总是BaseResponse类型。

我想做的是,如果View包含表单,POST -Action需要某种BaseRequest。当ViewModelBaseResponse时,我如何实现正确的模型绑定?

我已经尝试在XYZResponse中添加XYZRequest的属性,所以我可以绑定像

@Html.ChecBoxFor(m => m.RequestObject.SomeBooleanProperty)

,但这将生成name RequestObject。someboolean属性不能正确绑定到接受XYZRequest的POST-Action .

这种惯例是完全错误的,还是我错过了什么?

Update # 1

我还尝试创建一个类型为XYZRequest的新temporary对象,并像

一样绑定到它
@Html.CheckBoxFor(m = tmpReq.SomeBooleanProperty)

,它将渲染nametmp.SomeBooleanProperty,也不能绑定。

更新#2 -附加信息

设置如下结构。

  • BaseRequestabstract
  • GetOverviewRequest: BaseRequest
  • GetOverviewRequest具有类型string, int或任何其他复杂类型的属性,甚至ListsDictionaries

如果从BaseResponse继承的GetOverviewResponse返回给View并提供名为 TheProperty的属性类型的GetOverviewRequest绑定在

失败
@Html.TextBoxFor(m => m.TheProperty.SomeBooleanValue)

将尝试绑定到GetOverviewRequest对象中的TheProperty -property,该对象不存在。

如果GetOverviewRequest有一个叫做TheProperty的属性需要绑定,这可能会起作用。但是如果命名不同,绑定也会失败。

我只需要像

<input name="SomeBooleanValue">
<input name="SomeComplexType.SomeStringValue">
不是

<input name="TheProperty.SomeBooleanValue">
<input name="TheProperty.SomeComplexType.SomeStringValue">

更新#3 -添加示例项目

示例项目通过dropbox.com

更新#4 -解释,为什么@StephenMuecke的解决方案不起作用

如注释所述,其他问题的解决方案需要知道GetOverviewResponse -object中属性的名称。该属性名为TheProperty,因此我必须添加[Bind(Prefix = "TheProperty)]以启用正确的绑定。我真的不喜欢魔法弦。"TheProperty"是一个神奇的字符串。如果将TheProperty的名称更改为RenamedProperty,则整个绑定将失败。

。我现在正在寻找一种方法来动态地设置前缀。

[Bind(Prefix = GetOverviewResponse.NameOf(m => m.TheProperty))]

真的很棒。也许是某种自定义属性?由于BindAttribute是密封的,所以没有机会创建一个继承自此的。

任何想法?

ASP.. NET MVC 4属性重命名发布

MVC中的绑定工作在一个Name/Value字典上。所以如果你有:

public class BaseRequest
{
    public string prop1 {get; set;}
    public string prop2 {get; set;}
    public string prop3 {get; set;}
}

cshtml:

@Html.TextBoxFor(x => x.prop1)

则控制器接受的对象无关紧要:

public ActionResult MyAction(NotBaseRequest request)
{   
    //do something
}

new object taken in:

public class NotBaseRequest
{
    public string prop1 {get; set;}
}

MVC会绑定它,没有问题。

如果你想要绑定子对象那么你必须在控制器接收的对象中有基对象

public class BaseRequest
{
    public NotBaseRequest NotBaseRequest {get; set;}
}

cshtml

@Html.TextBoxFor(x => x.NotBaseRequest.prop1)
//<input type="text" name="NotBaseReqest.prop1" value /> 

MVC将使用name属性将值发送给控制器。

控制器

public ActionResult MyAction(OtherRequest request)
{
    //do something
}

你接受的对象可以被称为任何对象,只要它有NotBaseRequest。

新对象:

public class OtherRequest
{
    public NotBaseRequest NotBaseRequest {get; set;}
}

html对象的name属性将创建子对象并为其赋值。

正如注释所述,我已经创建了一些新的结构来实现我所需要的。

我创建了一个新的类BaseRequestWrapperResponse<TRequest>来封装Request -对象在Response

    public abstract class BaseRequestWrapperResponse<TRequest> : BaseResponse where TRequest : IRequestFromResponse

这个类目前有一个属性:

    public TRequest Request { get; set; }

接下来我创建了一个接口:

    public interface IRequestFromResponse

我的Requset -object将从中继承->将用于绑定。

在我的自定义模型绑定器覆盖protected override object CreateModel我检查if (modelType.GetInterfaces().Contains(typeof(IRequestFromResponse))),看看我的Request是否需要特殊处理。如果是这样,我将动态创建BindAttribute,并在normal绑定器完成其余工作之前设置它:

                var bindAttribute = new BindAttribute {Prefix = GetPropertyName<BaseRequestWrapperResponse<IRequestFromResponse>, IRequestFromResponse>(r => r.Request)};
            TypeDescriptor.AddAttributes(modelType, bindAttribute);

GetPropertyName的定义:

        private static string GetPropertyName<TSource, TProperty>(Expression<Func<TSource, TProperty>> propertyLambda)
    {
        var member = (MemberExpression)propertyLambda.Body;
        return member.Member.Name;
    }

参见:获取抽象泛型类中的属性名称