Follwing公约(多个)中给出。每个动作有一个类型的单个参数 BaseRequest 与视动作数据。在视图模型始终类型的 BaseResponse 。
我想要做的是,如果一个查看包含一个表单,在 POST 清议需要某种 BaseRequest 的。我怎样才能获得正确的模型作为结合的视图模型是 BaseResponse ?
我已经尝试过在 XYZResponse 添加 XYZRequest 属性,所以我可以绑定像
@ Html.ChecBoxFor(M = GT; m.RequestObject.SomeBooleanProperty)但这样会产生名称 RequestObject.SomeBooleanProperty将不能正确绑定到后操作其接受 XYZRequest 。
有什么完全错误的用这种公约的还是我失去了一些东西?
更新#1
我也尝试创建一个新的临时类型的对象 XYZRequest 并绑定到它像
@ Html.CheckBoxFor(M = TM preq.SomeBooleanProperty)这会使一个名称 tmp.SomeBooleanProperty 中也无法绑定。
更新#2 - 附加信息
以下结构被设置。
- BaseRequest 是摘要
- GetOverviewRequest : BaseRequest
- GetOverviewRequest 有类型的属性字符串, INT 或任何其他复杂类型,甚至列表或字典
如果在 GetOverviewResponse ,从 BaseResponse 继承,给出回查看并提供了一个命名属性的 利人 类型 GetOverviewRequest 绑定失败为
@ Html.TextBoxFor(M = GT; m.TheProperty.SomeBooleanValue)将尝试绑定到利人 -property在 GetOverviewRequest 对象,只是不存在。
这如果 GetOverviewRequest 有一个名为利人属性可能会工作绑定。但是,如果它的名称不同,结合也会失败。
我只希望像
<输入名称=SomeBooleanValue><输入名称=SomeComplexType.SomeStringValue>而不是
<输入名称=TheProperty.SomeBooleanValue><输入名称=TheProperty.SomeComplexType.SomeStringValue>更新#3 - 增加示例项目
通过dropbox示例项目
更新#4 - 解释,为什么从@StephenMuecke解决方案是不工作
正如评论所说,在其他问题的解决需要知道在 GetOverviewResponse -object属性的名称。该物业被命名为利人,所以我要补充 [装订(preFIX =利人)] 来使正确的结合。我真的不喜欢魔术字符串。和利人是一个神奇的字符串。如果一个人改变了利人的名称到 RenamedProperty ,整个绑定操作将失败。
所以。现在我正在寻找一种方法来设置preFIX一些实物动态。
[装订(preFIX = GetOverviewResponse.NameOf(M = GT; m.TheProperty))]将是真正真棒。也许某种自定义的属性?由于BindAttribute是密封的,没有机会创建一个从这个继承。
任何想法?
解决方案正如评论指出,我创造了一些新的结构来实现我所需要的。
我创建了一个新的类 BaseRequestWrapperResponse< TRequest> 封装请求 -object在响应
公共抽象类BaseRequestWrapperResponse< TRequest> :BaseResponse哪里TRequest:IRequestFromResponse本类有目前一个属性:
公共TRequest请求{搞定;组; }接下来我创建了一个接口:
公共接口IRequestFromResponse从我 Requset -object将继承 - >将用于结合
在我的自定义ModelBinder的覆盖保护覆盖对象CreateModel 我检查如果(modelType.GetInterfaces()。包含(typeof运算(IRequestFromResponse)))来看看我的请求需求特殊处理。如果是这样我创建 BindAttribute 动态和之前设置是正常粘结剂将完成剩下的:
VAR bindAttribute =新BindAttribute {preFIX = getPropertyName方法< BaseRequestWrapperResponse< IRequestFromResponse>中IRequestFromResponse>(R = GT; r.Request)}; TypeDescriptor.AddAttributes(modelType,bindAttribute);在这里getPropertyName方法定义:
私有静态字符串getPropertyName方法< TSource,TProperty>(防爆pression<&Func键LT; TSource,TProperty>> propertyLambda) { VAR成员=(MemberEx pression)propertyLambda.Body; 返回member.Member.Name; }另请参阅:获取的属性名称抽象泛型类
Follwing convention(s) are given. Each Action has a single parameter of type BaseRequest with data depending on the Action. The ViewModel is always of type BaseResponse.
What I'm trying to do is, that if a View contains a form, the POST-Action requires some sort of BaseRequest. How can I achieve correct-model binding as of the ViewModel is BaseResponse?
I already tried to add a property of XYZRequest in XYZResponse so I could bind like
@Html.ChecBoxFor(m => m.RequestObject.SomeBooleanProperty)but this will generate name RequestObject.SomeBooleanProperty which will not bind correctly to the POST-Action which accepts the XYZRequest.
Is there something completely wrong with this kind of conventions or am I missing something?
Update #1
I also tried creating a new temporary object of type XYZRequest and bind to it like
@Html.CheckBoxFor(m = tmpReq.SomeBooleanProperty)which will render a name of tmp.SomeBooleanProperty which also could not be bound.
Update #2 - additional information
Following structure is set.
- BaseRequest is abstract
- GetOverviewRequest : BaseRequest
- GetOverviewRequest has properties of type string, int or any other complex type and even Lists or Dictionaries
If the GetOverviewResponse, which inherits from BaseResponse, is given back to the View and provides a property named TheProperty of type GetOverviewRequest binding fails as of
@Html.TextBoxFor(m => m.TheProperty.SomeBooleanValue)will try to bind to TheProperty-property in the GetOverviewRequest object, which just not exists.
This may would work if GetOverviewRequest has a property called TheProperty to bind. But if it is named differently, binding will also fail.
I just want something like
<input name="SomeBooleanValue"> <input name="SomeComplexType.SomeStringValue">instead of
<input name="TheProperty.SomeBooleanValue"> <input name="TheProperty.SomeComplexType.SomeStringValue">Update #3 - added sample project
Sample project via dropbox
Update #4 - explanation, why solution from @StephenMuecke is not working
As mentioned in comments, the solution in other question needs to know the name of the property in the GetOverviewResponse-object. The property is named TheProperty, therefore I have to add [Bind(Prefix = "TheProperty)] to enable correct binding. I really don't like magic strings. And "TheProperty" is a magic string. If one changes the name of the TheProperty to RenamedProperty, the whole binding will fail.
So. I'm now looking for a way to set the prefix some-kind dynamically.
[Bind(Prefix = GetOverviewResponse.NameOf(m => m.TheProperty))]would be really awesome. Maybe some kind of a custom attribute? As of BindAttribute is sealed, there is no chance to create one inherited from this.
Any ideas?
解决方案As stated by comments I've created some new structure to achieve what I needed.
I created a new class BaseRequestWrapperResponse<TRequest> to encapsulate the Request-object in a Response
public abstract class BaseRequestWrapperResponse<TRequest> : BaseResponse where TRequest : IRequestFromResponseThis class has currently one property:
public TRequest Request { get; set; }Next I've created an interface:
public interface IRequestFromResponsefrom which my Requset-object will inherit -> will be used for binding.
In my custom modelbinder override of protected override object CreateModel I check if (modelType.GetInterfaces().Contains(typeof(IRequestFromResponse))) to see if my Request needs special handling. If so I create the BindAttribute dynamically and set it before the normal binder will do the rest:
var bindAttribute = new BindAttribute {Prefix = GetPropertyName<BaseRequestWrapperResponse<IRequestFromResponse>, IRequestFromResponse>(r => r.Request)}; TypeDescriptor.AddAttributes(modelType, bindAttribute);where GetPropertyName is defined:
private static string GetPropertyName<TSource, TProperty>(Expression<Func<TSource, TProperty>> propertyLambda) { var member = (MemberExpression)propertyLambda.Body; return member.Member.Name; }See also: Get name of property in abstract generic class
更多推荐
ASP.NET MVC 4财产为重命名发布
发布评论