ASP.NET MVC 4 属性-为发布重命名
ASP.NET MVC 4 property-renaming for posting
给出了以下约定。每个 Action
都有一个 BaseRequest
类型的参数,其数据取决于 Action
。 ViewModel
始终是 BaseResponse
.
类型
我想做的是,如果 View
包含一个表单,POST
-Action 需要某种 BaseRequest
。
从 ViewModel
开始,我如何实现正确的模型绑定是 BaseResponse
?
我已经尝试在 XYZResponse
中添加 XYZRequest
的 属性 这样我就可以像
那样绑定
@Html.ChecBoxFor(m => m.RequestObject.SomeBooleanProperty)
但这会生成 name
RequestObject.SomeBooleanProperty,它不会正确绑定到接受 XYZRequest
.
的 POST-Action
这种约定是否完全错误或者我遗漏了什么?
更新#1
我还尝试创建一个 XYZRequest
类型的新 temporary
对象并像
那样绑定到它
@Html.CheckBoxFor(m = tmpReq.SomeBooleanProperty)
这将呈现 name
的 tmp.SomeBooleanProperty
也无法绑定。
更新 #2 - 附加信息
设置了以下结构。
BaseRequest
是 abstract
GetOverviewRequest
: BaseRequest
GetOverviewRequest
具有 string
、int
或任何其他复杂类型甚至 Lists
或 Dictionaries
类型的属性
如果继承自BaseResponse
的GetOverviewResponse
返回给View
并提供一个名为[=48=的属性 ] 类型 GetOverviewRequest
绑定失败
@Html.TextBoxFor(m => m.TheProperty.SomeBooleanValue)
将尝试绑定到 GetOverviewRequest
对象中的 TheProperty
-属性,该对象不存在。
如果 GetOverviewRequest
有一个名为 TheProperty
的 属性 来绑定,这可能会起作用。但如果命名不同,绑定也会失败。
我只想要
<input name="SomeBooleanValue">
<input name="SomeComplexType.SomeStringValue">
而不是
<input name="TheProperty.SomeBooleanValue">
<input name="TheProperty.SomeComplexType.SomeStringValue">
更新 #3 - 添加了示例项目
Sample project via dropbox.com
更新 #4 - 解释,为什么@StephenMuecke 的解决方案不起作用
如评论中所述,其他问题的解决方案需要知道 GetOverviewResponse
-object 中 属性 的名称。 属性 被命名为 TheProperty
,因此我必须添加 [Bind(Prefix = "TheProperty)]
才能启用正确的绑定。我真的不喜欢魔术弦。 "TheProperty"
是一个神奇的字符串。如果将 TheProperty
的名称更改为 RenamedProperty
,整个绑定将失败。
所以。我现在正在寻找一种动态设置前缀的方法。
[Bind(Prefix = GetOverviewResponse.NameOf(m => m.TheProperty))]
真的很棒。也许某种自定义属性?由于 BindAttribute 是密封的,因此没有机会创建一个继承自此的。
有什么想法吗?
MVC 中的绑定适用于名称/值字典。所以如果你有:
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
}
接收到的新对象:
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 将使用名称属性将值发送到控制器。
控制器
public ActionResult MyAction(OtherRequest request)
{
//do something
}
你拿进来的对象,只要里面有NotBaseRequest,随便叫什么都行。
新对象:
public class OtherRequest
{
public NotBaseRequest NotBaseRequest {get; set;}
}
html 对象的名称属性将创建子对象并为其赋值。
如评论所述,我创建了一些新结构来实现我的需要。
我创建了一个新的 class BaseRequestWrapperResponse<TRequest>
来将 Request
对象封装在 Response
中
public abstract class BaseRequestWrapperResponse<TRequest> : BaseResponse where TRequest : IRequestFromResponse
这个class目前有一个属性:
public TRequest Request { get; set; }
接下来我创建了一个界面:
public interface IRequestFromResponse
我的 Requset
-对象将从中继承 -> 将用于绑定。
在我的自定义模型绑定器中覆盖 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;
}
另请参阅:
给出了以下约定。每个 Action
都有一个 BaseRequest
类型的参数,其数据取决于 Action
。 ViewModel
始终是 BaseResponse
.
我想做的是,如果 View
包含一个表单,POST
-Action 需要某种 BaseRequest
。
从 ViewModel
开始,我如何实现正确的模型绑定是 BaseResponse
?
我已经尝试在 XYZResponse
中添加 XYZRequest
的 属性 这样我就可以像
@Html.ChecBoxFor(m => m.RequestObject.SomeBooleanProperty)
但这会生成 name
RequestObject.SomeBooleanProperty,它不会正确绑定到接受 XYZRequest
.
这种约定是否完全错误或者我遗漏了什么?
更新#1
我还尝试创建一个 XYZRequest
类型的新 temporary
对象并像
@Html.CheckBoxFor(m = tmpReq.SomeBooleanProperty)
这将呈现 name
的 tmp.SomeBooleanProperty
也无法绑定。
更新 #2 - 附加信息
设置了以下结构。
BaseRequest
是abstract
GetOverviewRequest
:BaseRequest
GetOverviewRequest
具有string
、int
或任何其他复杂类型甚至Lists
或Dictionaries
类型的属性
如果继承自BaseResponse
的GetOverviewResponse
返回给View
并提供一个名为[=48=的属性 ] 类型 GetOverviewRequest
绑定失败
@Html.TextBoxFor(m => m.TheProperty.SomeBooleanValue)
将尝试绑定到 GetOverviewRequest
对象中的 TheProperty
-属性,该对象不存在。
如果 GetOverviewRequest
有一个名为 TheProperty
的 属性 来绑定,这可能会起作用。但如果命名不同,绑定也会失败。
我只想要
<input name="SomeBooleanValue">
<input name="SomeComplexType.SomeStringValue">
而不是
<input name="TheProperty.SomeBooleanValue">
<input name="TheProperty.SomeComplexType.SomeStringValue">
更新 #3 - 添加了示例项目
Sample project via dropbox.com
更新 #4 - 解释,为什么@StephenMuecke 的解决方案不起作用
如评论中所述,其他问题的解决方案需要知道 GetOverviewResponse
-object 中 属性 的名称。 属性 被命名为 TheProperty
,因此我必须添加 [Bind(Prefix = "TheProperty)]
才能启用正确的绑定。我真的不喜欢魔术弦。 "TheProperty"
是一个神奇的字符串。如果将 TheProperty
的名称更改为 RenamedProperty
,整个绑定将失败。
所以。我现在正在寻找一种动态设置前缀的方法。
[Bind(Prefix = GetOverviewResponse.NameOf(m => m.TheProperty))]
真的很棒。也许某种自定义属性?由于 BindAttribute 是密封的,因此没有机会创建一个继承自此的。
有什么想法吗?
MVC 中的绑定适用于名称/值字典。所以如果你有:
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
}
接收到的新对象:
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 将使用名称属性将值发送到控制器。
控制器
public ActionResult MyAction(OtherRequest request)
{
//do something
}
你拿进来的对象,只要里面有NotBaseRequest,随便叫什么都行。
新对象:
public class OtherRequest
{
public NotBaseRequest NotBaseRequest {get; set;}
}
html 对象的名称属性将创建子对象并为其赋值。
如评论所述,我创建了一些新结构来实现我的需要。
我创建了一个新的 class BaseRequestWrapperResponse<TRequest>
来将 Request
对象封装在 Response
public abstract class BaseRequestWrapperResponse<TRequest> : BaseResponse where TRequest : IRequestFromResponse
这个class目前有一个属性:
public TRequest Request { get; set; }
接下来我创建了一个界面:
public interface IRequestFromResponse
我的 Requset
-对象将从中继承 -> 将用于绑定。
在我的自定义模型绑定器中覆盖 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;
}
另请参阅: