ASP.NET MVC 4财产为重命名发布 [英] ASP.NET MVC 4 property-renaming for posting

查看:200
本文介绍了ASP.NET MVC 4财产为重命名发布的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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.com

示例项目

更新#4 - 解释,为什么从@StephenMuecke解决方案是不工作

正如评论所说,在其他问题的解决需要知道在 GetOverviewResponse -object属性的名称。该物业被命名为利人,所以我要补充 [装订(preFIX =利人)] 来使正确的结合。我真的不喜欢魔术字符串。和利人是一个神奇的字符串。如果一个人改变了利人的名称 RenamedProperty ,整个绑定操作将失败。

所以。现在我正在寻找一种方法来设置preFIX一些实物动态。

  [装订(preFIX = GetOverviewResponse.NameOf(M = GT; m.TheProperty))]

将是真正真棒。也许某种自定义的属性?由于BindAttribute是密封的,没有机会创建一个从这个继承。

任何想法?


解决方案

正如评论指出,我创造了一些新的结构来实现我所需要的。

我创建了一个新的类 BaseRequestWrapperResponse< TRequ​​est> 封装请求 -object在响应

 公共抽象类BaseRequestWrapperResponse< TRequ​​est> :BaseResponse哪里TRequ​​est:IRequestFromResponse

本类有目前一个属性:

 公共TRequ​​est请求{搞定;组; }

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

 公共接口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.com

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 : IRequestFromResponse

This class has currently one property:

    public TRequest Request { get; set; }

Next I've created an interface:

    public interface IRequestFromResponse

from 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财产为重命名发布的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆