ASP.NET MVC 3 ContentResult не будет принимать класс, который унаследован от другого класса - PullRequest
0 голосов
/ 10 июля 2011

Далее следует еще один вопрос, который я задал здесь: Поиск ближайших объектов с помощью элемента управления REST Bing Maps

В приведенном выше вопросе в цикле for функции DisplayResults (response) я добавил следующий код:

    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 разработчика, предоставив им локализованный набор адресов, соответствующих их обнаруженному местоположению (этот код приведен в моем предыдущем посте).

Вот код ContentResult в HomeController:

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

Этот код работает с соответствующим методом POST, когда мой класс Address выглядит так:

Адрес публичного класса { приватная двойная широта; частный двойной _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 от сервера ... Мне просто не ясно, в чем причина. Вот пример того, о чем я говорю (ps, если вы используете какой-либо из приведенного ниже кода, просто подсказка, что вы должны выяснить, как использовать словарь для сериализации ... это НАМНОГО быстрее, но люди более знакомы с отражением, вот что я собираюсь здесь):

так быстро, для класса Address у меня будет:

Адрес: BaseClass

и конструктор будет ...

Адрес: база («Адрес») { // хотя 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 :)

Спасибо!

1 Ответ

0 голосов
/ 11 июля 2011

Итак, первая проблема здесь в том, что область вашего вопроса way too big.

Вы начинаете с отправки запроса AJAX на этот сервер «черного ящика». Но потом выясняется, что у вас есть код для сервера, так почему я в первую очередь беспокоюсь об AJAX-запросе? Места для начала:

  1. Вы уверены, что сериализация работает правильно? У вас есть тест, который доказывает, что ваш базовый класс сериализации действительно работает? (это должно быть тривиально, чтобы подделать ввод) Если нет, вы, вероятно, получите ошибку.
  2. Правильно ли попадают данные в MongoDB? Если нет, вы можете вызвать исключение и получить ошибку. Обратите внимание, что драйвер CSharp имеет собственную сериализацию . Вы можете разрушить это.
  3. Можете ли вы подтвердить, что те же данные попадают в представление? Возможно, ваш взгляд взрывается, потому что вы зависите от какого-то поля, которое не существует правильно.

В общем, эту проблему должно быть очень легко диагностировать с помощью типового охвата модульных тестов. Вы внесли одно изменение в один класс, поэтому ваш набор тестов должен выдавать довольно четкие сообщения, вероятно одно из трех выше.

Если в вашем наборе тестов не было ошибок, значит, вы упускаете некоторые важные тесты.

Если у вас нет тестового покрытия, сейчас самое время начать.

...