ASP.NET MVC 3 ContentResult 将不接受从另一个类继承的类

Posted

技术标签:

【中文标题】ASP.NET MVC 3 ContentResult 将不接受从另一个类继承的类【英文标题】:ASP.NET MVC 3 ContentResult Will Not Accept Class That Inherits From Another Class 【发布时间】:2011-07-10 18:37:42 【问题描述】:

这是我在这里提出的另一个问题:Find nearby entities with Bing Maps REST control

在上面的问题中,在函数 DisplayResults(response) 的 for 循环中,我添加了以下代码:

    var loc = new Array();
    loc[0] = results[i].Longitude;
    loc[1] = results[i].Latitude;

    var address = 
        AddressLine1: results[i].Address,
        City: results[i].City,
        State: results[i].StateOrProvince,
        PostalCode: results[i].PostalCode,
        Latitude: results[i].Latitude,
        Longitude: results[i].Longitude,
        Country: results[i].CountryOrRegion,
        ID: results[i].UniqueId
    ;

    $.ajax(
        url: "/Home/AddAddressToCollection",
        type: 'post',
        data: JSON.stringify(address),
        contentType: 'application/json',
        dataType: 'json'
    );

上面的代码从结果数据集中包含的每个地址构造一个地址,并将其发送回 ContentResult,该结果返回 null,因为它的目的是将每个地址存储到后端,即 MongoDB。您可能想知道我为什么采用这种方法 - 地址是 MongoDB 的种子数据。这个想法是,这是一个开源项目,我想添加一些个性化来使用开发人员的 GeoLocation,方法是为他们提供一组与他们检测到的位置相对应的本地化地址(该代码都在我之前的帖子中)。

这是 HomeController 中 ContentResult 的代码:

    [HttpPost]
    public ContentResult AddAddressToCollection(Address address)
    
        address.GeoInsert(_dbName, ref _repository);
        return null;
    

当我的 Address 类如下所示时,此代码可以与相应的 POST 方法一起使用:

公开课地址 私人双纬度; 私人双 _longitude;

    [Key]
    [Required]
    [HiddenInput(DisplayValue=false)]
    public string ID  get; set; 

    [Required]
    [HiddenInput(DisplayValue = false)]
    public virtual Guid AccountID  get; set; 

    [Required]
    [Display(Name = "Address Line 1")]
    public string AddressLine1  get; set; 

    [Display(Name = "Address Line 2")]
    public string AddressLine2  get; set; 

    [Required]
    [Display(Name = "City")]
    public string City  get; set; 

    [Required]
    [Display(Name = "State")]
    public string State  get; set; 

    [Required]
    [Display(Name = "Zip Code")]
    public string PostalCode  get; set; 

    public string Country  get; set; 

    [Required]
    [HiddenInput(DisplayValue = false)]
    public double[] Location  get; set; 

    [Required]
    [HiddenInput(DisplayValue = false)]
    public double Latitude
    
        get  return _latitude; 
        set
        
            Location[1] = value;
            _latitude = value;
        
    

    [Required]
    [HiddenInput(DisplayValue = false)]
    public double Longitude
    
        get  return _longitude; 
        set
        
            Location[0] = value;
            _longitude = value;
        
    

    public Address()
    
        Location = new double[2];
    

    public void GeoInsert(string dbName, ref Repository repository)
    
        repository.MongoGeoInsert(dbName, this);
    

    public Dictionary<Address, double> GeoNear(string dbName, ref Repository repository, double maxKilometers, int limitResults)
    
        return repository.MongoGeoNear<Address>(dbName, this.Latitude, this.Longitude, maxKilometers, limitResults);
    

   

但这就是我好奇的地方......虽然我现在不需要这个,但我最初尝试让我的模型中的所有类都从同一个基类继承,以帮助我使用一些自定义序列化方法.当我从这样一个类继承......让我们称之为 BaseClass,POST 不再工作,我从服务器收到 500 响应......我只是不清楚原因是什么。这是我正在谈论的一个示例(p.s.如果您碰巧使用以下任何代码,只是提示您应该弄清楚如何使用 Dictionary 进行序列化......它要快得多,但人们更熟悉有反射,所以这就是我要在这里做的):

这么快,对于 Address 类,我将拥有:

地址:基类

构造函数是……

地址 : base("地址") //尽管 base("Address") 不是必需的,除非你使用字典 //序列化方法

现在是 BaseClass...

public class Serialization

    public abstract class BaseObject
    
        [BsonId(IdGenerator = typeof(CombGuidGenerator))]
        public Guid? Id  get; set; 

        public string ObType  get; private set; 

        public BaseObject() : this("base")  

        public BaseObject(string obType)
        
            ObType = obType;
            Id = Guid.NewGuid();
        

        public virtual BaseObject Parse(XElement xml)
        
            PropertyInfo[] properties = this.GetType().GetProperties();

            foreach (var property in properties)
            
                ElementName attribute = Attribute.GetCustomAttribute(property, typeof(ElementName)) as ElementName;
                if (attribute == null) continue;

                object value = null;
                string stringValue = xml.Element(attribute.Name).Value;

                switch (property.PropertyType.Name.ToLower())
                
                    case "double":
                        
                            value = double.Parse(stringValue);
                            break;
                        
                    default:
                        
                            value = stringValue;
                            break;
                        
                

                property.SetValue(this, value, null);
            

            return this;
        

    

    public class Serializer
    
        public static T Deserialize<T>(XElement xml)
            where T : BaseObject, new()
        
            BaseObject obj = new T() as BaseObject;
            if (obj != null)
            
                //populate obj properties...
                obj.Parse(xml);
            
            return obj as T;
        
    

好的,我认为这应该是足够的信息......有什么想法不起作用?希望我在这里没有遗漏一些非常明显的东西......但我做的 Silverlight 比 ASP.NET 编程要多得多,所以我完全有可能是 0:)

谢谢!

【问题讨论】:

你能打开 firebug 告诉我们你遇到了什么错误吗?? 是的,这是一个非常标准的 500 错误:POST /Home/AddAddressToCollection 500 Internal Server Error 我认为它与 MVC 框架如何处理内容和操作结果有关,因为我知道代码客户端正在工作(因为当我不从 BaseClass 继承时它工作) 【参考方案1】:

所以这里的第一个问题是你的问题的范围方式太大了。

您首先向这个“黑匣子”服务器发送一个 AJAX 请求。但后来发现你有服务器的代码,那么我为什么要关心 AJAX 请求呢?开始的地方:

    您确定序列化工作正常吗?您是否有测试证明您的自定义序列化基类确实有效? (伪造输入应该是微不足道的)如果不是,你可能会得到一个错误。 数据是否正确进入 MongoDB?如果没有,您可能会抛出异常并得到错误。请注意 CSharp 驱动程序has its own serialization。你可能会破坏它。 您能否确认相同的数据正在进入视图?您的视图可能会爆炸,因为您依赖于某些不正确存在的字段。

总而言之,这个问题应该很容易通过典型的单元测试覆盖率来诊断。您对一个类进行了一项更改,因此您的测试套件应该会抛出一些非常明确的消息,可能是上述三个之一。

如果您的测试套件没有抛出任何错误,那么您显然错过了一些重要的测试。

如果您没有任何测试覆盖率,现在可能是开始的好时机。

【讨论】:

序列化代码已经过彻底的测试,但我在这个例子中没有使用序列化。为了澄清,我添加这个类是有远见的,我可能想在以后使用序列化,但这不是问题。我知道代码有效,所以我很确定它与引发内部错误的 MVC 框架有关。沿着这些思路 - 当然,我没有考虑这个错误,但如果我有一个针对这个错误的测试,我为什么要问这个问题?! 盖茨,如果你被我的 Mongo 代码吓跑了,我写了一组自定义的 Mongo 操作来简化 Mongo 的使用。我对 Mongo 序列化非常熟悉,这与此无关。为了简化互操作性并减轻传输/存储成本,在传递或存储有关特定类的数据时,我经常使用自定义 xml/json 序列化程序。

以上是关于ASP.NET MVC 3 ContentResult 将不接受从另一个类继承的类的主要内容,如果未能解决你的问题,请参考以下文章

我们是不是正在使用 .Net 3.5 中的 MVC 框架转向经典 ASP?

(转)表单和HTML辅助方法 - ASP.NET MVC 3

ASP .NET 5 MVC 6 Identity 3 Roles Claims Groups [关闭]

ASP.NET MVC 3 文件夹结构

ASP.NET Core MVC 入门到精通 - 3. 使用MediatR

ASP.NET MVC 3 和 NHibernate 脚手架