ASP.. NET MVC 4属性重命名发布
本文关键字:重命名 属性 NET MVC ASP | 更新日期: 2023-09-27 18:04:44
给出了以下约定:每个Action
都有一个类型为BaseRequest
的参数,其数据取决于Action
。ViewModel
总是BaseResponse
类型。
我想做的是,如果View
包含表单,POST
-Action需要某种BaseRequest
。当ViewModel
是BaseResponse
时,我如何实现正确的模型绑定?
我已经尝试在XYZResponse
中添加XYZRequest
的属性,所以我可以绑定像
@Html.ChecBoxFor(m => m.RequestObject.SomeBooleanProperty)
,但这将生成name
RequestObject。someboolean属性不能正确绑定到接受XYZRequest
的POST-Action .
这种惯例是完全错误的,还是我错过了什么?
Update # 1
我还尝试创建一个类型为XYZRequest
的新temporary
对象,并像
@Html.CheckBoxFor(m = tmpReq.SomeBooleanProperty)
,它将渲染name
的tmp.SomeBooleanProperty
,也不能绑定。
更新#2 -附加信息
设置如下结构。
-
BaseRequest
是abstract
-
GetOverviewRequest
:BaseRequest
-
GetOverviewRequest
具有类型string
,int
或任何其他复杂类型的属性,甚至Lists
或Dictionaries
如果从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是密封的,所以没有机会创建一个继承自此的。
任何想法?
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;
}
参见:获取抽象泛型类中的属性名称