ASP.NET MVC 3 - проверка модели - PullRequest
2 голосов
/ 17 ноября 2011

Я только изучаю MVC, и у меня есть несколько вопросов о дизайне / как все должно работать.

Я использую MVC 3 и Razor с классами Entity Framework (например, Location), и я собираюсь создать класс друзей с аннотациями Validation. В моем виде у меня есть частичное представление, которое отображает DevExpress TreeView (с использованием списка местоположений) и форму для создания / редактирования местоположений в дереве. У меня есть LocationController, LocationManagementView, LocationManagementPartialView (содержит код для дерева) и LocationModel. LocationModel будет содержать класс партнера и получать методы для получения дочерних элементов (дочерние элементы выбираются только после расширения узла). У меня есть сервисная оболочка (для моего сервисного клиента), которая будет внедрена с использованием StructureMap.

Должен ли я вставить служебную оболочку в конструктор контроллера или в конструктор модели?

Кроме того, в моей модели есть методы get, которые используют служебную оболочку для извлечения данных из базы данных (принадлежат ли эти методы здесь, в модели?): Например, GetChildren для представления дерева.

Кроме того, правильно ли хранить класс «Местоположение» в модели?

Я хочу убедиться, что я хорошо спроектировал это приложение, поскольку оно является частью гораздо большего проекта. Любые указатели дизайна очень ценятся. Я читал блог ScottGu для материала MVC.

Ссылка: http://weblogs.asp.net/scottgu/archive/2010/01/15/asp-net-mvc-2-model-validation.aspx

1 Ответ

3 голосов
/ 17 ноября 2011

Вот пара рекомендаций для вашей «рамки».

Entity Framework

Для каждой из ваших моделей, возвращенных из EF, извлеките интерфейс модели EF и используйте интерфейс в качестве источника данных, а не реализованныеEF Class.Причина этого заключается в том, что если вы решите использовать другой источник данных для какой-либо одной или нескольких моделей (или всей Entity Framework), вы можете просто убедиться, что ваш новый уровень данных возвращает те же интерфейсы, без необходимости изменения всей сети.код.Недостатком является то, что ваши интерфейсы обновляются при внесении изменений в модель.

Это также позволяет моделям представлений реализовывать интерфейс модели EF (с дополнительной логикой на ваш выбор).Это выгодно, если все ваши вызовы для вставок / обновлений уровня данных принимают одинаковые возвращаемые модели интерфейса.Это позволяет создавать несколько моделей с различными требованиями, которые соответствуют требованиям уровня данных для вставки / обновления.Недостатком является то, что на вашем уровне данных вам придется [создать новую модель EF] / [получить модель для обновления] и сопоставить поля из интерфейса с моделью.

Просмотр моделей

Я настоятельно рекомендую, чтобы каждая модель представления была не фактической моделью (моделями), которые должны отображаться, а классом, который содержит модель (ы).Примеры:

public class Car  //Not what I recommend passing to a view
{
    public string Make { get; set; }
    public string Model { get; set; }
}

//Pass this to the view, i'll explain why...
public class CarViewModel : IPartialViewCar      {
    public Car Car { get; set; }
    public ColorCollection { get; set; }
}

Передав пример "CarViewModel", вы можете отделить частичные виды от представлений.Вот как (с использованием моделей выше):

public interface IPartialViewCar  
{
    public Car { get; }
}

[BuildCar.cshtml]
@Model MyNameSpace.Models.Car

@Html.EditorFor(model)

[PartialViewCar.cshtml]
@Model MyNameSpace.Models.IPartialViewCar  

@Html.EditorFor(model)  //something like that..

Теперь в любое время, когда вы хотите использовать PartialViewCar, вам просто нужно создать модель, которая реализует интерфейс IPartialViewCar, в основном отделяя частичное представление от представления.

Валидация

Я бы порекомендовал создать интерфейсы (классы, если вы действительно хотите, но на самом деле в этом нет необходимости), в которых есть вся логика валидации.

Допустим, мы хотим, чтобы анонимные пользователи вводили как марку, так и модель, но зарегистрированные пользователи должны вводить только марку.Как это можно сделать легко, вот как: (расширяя более подробно предыдущий код)

public interface IAnonymouseCarValidation
{
    [required]
    public string Make { get; set; }
    [required]
    public string Model { get; set; }
}

public interface IRegisteredCarValidation
{
    [required]
    public string Make { get; set; }
}

public interface ICar
{
    public string Make { get; set;}
    public string Model { get; set; }
}

[updating the Car model to abstract and use an interface now]
public abstract class Car : ICar
{
    //maybe some constructor logic for all car stuff

    public string Make { get; set;}
    public string Model { get; set; }

    //maybe some methods for all car stuff
}

//MetadataType tells MVC to use the dataannotations on the
//typeof class/interface for validation!
[MetadataType(typeof(AnonymouseCarValidation))]
public class AnonymousCar : Car
{
}


[MetadataType(typeof(AnonymouseCarValidation))]
public class RegisteredCar : Car
{
}

[Now update the ViewModel]
public class CarViewModel : IPartialViewCar     
{
    public ICar Car { get; set; }  //this is now ICar 
    public ColorCollection { get; set; }
}

Теперь вы можете создать AnonymouseCar или RegisteredCar, передать его в CarViewModel и позволить MVCпозаботиться о проверке.Когда вам нужно обновить проверку, вы обновляете единый интерфейс.Недостатком этого является то, что он кажется довольно сложным.

Инъекция и запросы данных

Я предпочитаю стараться сделать действия контроллера максимально простыми и не включатькод там, чтобы получить данные.Причина, по которой я решил не делать этого, заключается в том, что я не люблю повторять код.Например:

public class AccountControllers
{
    DataServer _Service;

    public AccountControllers(DataServer Service)
    {
        this._Service = Service;
    }

    public ActionResult ShowProfiles()
    {
        ProfileViewModel model = new ProfileViewModel();
        model.Profiles = this._Service.Profiles();
        return View(model);
    }

    public ActionResult UpdateProfile(ProfileViewModel updatedModel)
    {
        service.UpdateProfile(updatedModel);

        ProfileViewModel model = new ProfileViewModel();
        model.Profiles = this._Service.Profiles();
        return View(model);
    }
}

Вместо этого я бы сделал что-то вроде: (не полностью)

    public ActionResult ShowProfile(Guid ID)
    {
        ProfileViewModel model = new ProfileViewModel(this._service);
        return View(model);
    }

    public ActionResult UpdateProfile(ProfileViewModel updatedModel)
    {
        // pass in the service, or use a property or have SetService method
        updatedModel.Update(this._service)

        ProfileViewModel model = new ProfileViewModel(this._service);
        return View(model);
    }

public class ProfileViewModel()
{
    DataServer _Service;
    Profile _Profile
    public ProfileViewModel()
    {
    }

    public ProfileViewModel(DataServer Service)
    {
        this._Service = Service;
    }


    public Profile Profiles()
    {
        get
        {
            if (this._service == null)
            {
                throw new InvalidOperationException("Service was not set.");
            }
            return = Service.Profiles(ID);
    }

Это означает, что профили перечисляются ТОЛЬКО при запросе, яне надо самому заселять.Как правило, меньше ошибок, если я использую код в своих интересах, вместо того, чтобы требовать от меня или других программистов ручного заполнения моделей.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...