ASP.net MVC v2 - 调试模型绑定问题 - BUG?

发布于 2024-08-09 22:42:21 字数 2361 浏览 6 评论 0原文

我在尝试调试为什么 MVC 在给定情况下没有正确绑定时遇到了很大的困难...

基本上,我的操作接收一个复杂的对象,而该对象又具有一个复杂的子对象 - Activity.Location。 State(其中 Activity 是操作所需的复杂对象,Location 是复杂的子对象,State 只是一个字符串)。

现在我建立了一个测试项目,据我所知,它完全模仿了我的实际场景,在这个测试用例中,绑定有效...但在我的实际项目中,与 Activity 的绑定有效,但与 Location 无效...通过在 Locaiton 属性中放置断点,我可以看出 MVC 正在从 Activity 中检索复杂的 Location 对象,但它没有设置任何属性...

我正在尝试调试该问题,但我需要访问 MVC v2 预览2 个我似乎无法追踪的符号...我想看看它在拉出位置对象后实际上在做什么(出于某种原因,我认为它可能在内部失败,但吞下了异常)。

关于我可以在这里做什么的任何想法......

干杯 安东尼

更新:

好的,我按照 JW 的建议做了,直接引用 MVC 项目...

我发现了问题,并且有一个我忽略的非常小的差异...结果我发现 MVC 目前不支持多个级别涉及模型绑定时的接口继承...请参阅以下内容...

//MODEL
public class Location : ILocation
{
    ...
}

public interface ILocation : ILocationCore
{
    ...
}

public interface ILocationCore    //In my sample I didn't have this second level interface
{
    ...
    //MVC doesn't find any of these properties
    ...
}


public class Activity : IActivity
{
    ...
}

public interface IActivity : IActivityCore
{
    ILocation Location { get; set; }   //MVC finds this and reads its meta type as an ILocation
    //Also the implementation of this Location within Activity will always return a instance - our IoC takes care of that, so MVC should never have to create the instance
}

public interface IActivityCore
{
    ...
}

//CONTROLLER
public ActionResult Create(Activity activity)
{
}

因此,我发现 MVC 找到位置并将其元类型读取为 ILocation,但是当在 DefaultModelBinder 中运行 GetModelProperties 时,会发生以下情况 -

    protected virtual PropertyDescriptorCollection GetModelProperties(ControllerContext controllerContext, ModelBindingContext bindingContext) {
        return GetTypeDescriptor(controllerContext, bindingContext).GetProperties();
        //This return no properties
    }

    protected virtual ICustomTypeDescriptor GetTypeDescriptor(ControllerContext controllerContext, ModelBindingContext bindingContext) {
        return new AssociatedMetadataTypeTypeDescriptionProvider(bindingContext.ModelType).GetTypeDescriptor(bindingContext.ModelType);
        //bindingContext.ModelType - is ILocation
    }

因此我现在假设 TypeDescriptionProvider 不支持这种继承风格,对此我感到非常惊讶。另外查看 v1 源代码,它看起来像是在 v2 中引入的 - 但 v1 可能无法支持我想要做的事情。

我不会说这确实是一个错误,但我尝试用具体的类替换我的接口,并且效果很好。因此,这种行为并不是我所期望的,并且有点不一致。

有什么想法吗???我本以为这种继承并不相当标准,但会经常发生,足以满足需要。感谢您的回复。

干杯

I am having more than a little difficulty trying to debug why MVC is not binding correctly in a given case I have...

Basically, I have my action which receives a complex object which in turn has a complex child object - Activity.Location.State (Where Activity is the complex object that the action expects, Location is a complex child object and State is just a string).

Now I set up a test project which as far as I can tell exactly mimics the actually scenario I have, in this test case the binding works... But in my actually project, the binding to Activity works but not to Location... By putting break points within the Locaiton property I can tell that MVC is retrieving the complex Location object from the Activity, but its not setting any of the properties...

I am trying to debug the issue but I need access to the MVC v2 preview 2 symbols which I can't seem to track down... I would like to see what it is actually doing once it pulls out the location object (for some reason I think it might be failing internally but swallowing the exception).

Any ideas on what I could do here...

Cheers
Anthony

UPDATE:

Ok I did what J.W. suggested and directly reference the MVC project...

I found the problem and there was one very small difference that I overlooked... As I result I found out that MVC does not currently support multiple levels of INTERFACE inheritance when it comes to model binding... See the following...

//MODEL
public class Location : ILocation
{
    ...
}

public interface ILocation : ILocationCore
{
    ...
}

public interface ILocationCore    //In my sample I didn't have this second level interface
{
    ...
    //MVC doesn't find any of these properties
    ...
}


public class Activity : IActivity
{
    ...
}

public interface IActivity : IActivityCore
{
    ILocation Location { get; set; }   //MVC finds this and reads its meta type as an ILocation
    //Also the implementation of this Location within Activity will always return a instance - our IoC takes care of that, so MVC should never have to create the instance
}

public interface IActivityCore
{
    ...
}

//CONTROLLER
public ActionResult Create(Activity activity)
{
}

Hence what I have found is that MVC finds the Location and reads its meta type as an ILocation, but when GetModelProperties is run within the DefaultModelBinder the following occurs -

    protected virtual PropertyDescriptorCollection GetModelProperties(ControllerContext controllerContext, ModelBindingContext bindingContext) {
        return GetTypeDescriptor(controllerContext, bindingContext).GetProperties();
        //This return no properties
    }

    protected virtual ICustomTypeDescriptor GetTypeDescriptor(ControllerContext controllerContext, ModelBindingContext bindingContext) {
        return new AssociatedMetadataTypeTypeDescriptionProvider(bindingContext.ModelType).GetTypeDescriptor(bindingContext.ModelType);
        //bindingContext.ModelType - is ILocation
    }

Hence I am assuming at this point that TypeDescriptionProvider doesn't support this style of inheritance, which i am quite surprised by. Also looking at the v1 source it looks like this was introduced with v2 - but v1 mightn't have been able to support what I am trying to do anyway.

I wouldn't say that this is really a bug, but I tried replacing my the interfaces with concrete classes and it worked fine. Hence the behavior isn't really what I would expect and is a little inconsistent.

Any thoughts??? I would have thought that this inheritance was not fairly standard but would occur often enough to be catered for. Thanks for the reply.

Cheers

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

黎夕旧梦 2024-08-16 22:42:21

事实证明,这种行为是由于接口继承的工作原理而设计的。接口不定义实现,因此 ILocation 不会“继承”ILocationSource 的属性。相反,ILocation 仅定义具体实现必须实现的内容。

有关完整详细信息,包括定义此行为的 CLI(公共语言基础设施)规范部分,请查看:http://haacked.com/archive/2009/11/10/interface-inheritance-esoterica.aspx

Turns out this behavior is by design due to how interface inheritance works. Interfaces do not define implementations, thus ILocation doesn't "inherit" the properties of ILocationSource. Rather, ILocation only defines what a concrete implementation must implement.

For the full details including the section of the CLI (Common Language Infrastructure) spec which defines this behavior, check out: http://haacked.com/archive/2009/11/10/interface-inheritance-esoterica.aspx

对不⑦ 2024-08-16 22:42:21

我只是参考codeplex上发布的asp.net mvc2源代码。我就是这样做的,非常简单。

当您通过源代码进行调试时,它将让您更好地理解。

I would simply reference to the asp.net mvc2 source code published in codeplex. I did that, it's very straightforward.

It will give you much better understanding when you debugging through the source code.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文