Как создать экземпляр IController в ASP.NET MVC 4 (предварительный просмотр), чтобы IController.ValidateModel работал? - PullRequest
0 голосов
/ 12 января 2012

У меня есть необходимость вручную создавать экземпляры некоторых контроллеров и, следовательно, иметь этот код:

var controller = Activator.CreateInstance(typeof(AccountController), 
                 repository) as AccountController;

В AccountController у меня есть метод, подобный этому:

[AllowAnonymous]
[HttpPost]
public ApiJsonResult LogOn(LogOnAccountDto model)
{
     ValidateModel(model);
     if (ModelState.IsValid)
     {
      //...
     }
}

Я хочу, чтобы мойModelState.IsValid работает, поэтому я вызываю ValidateModel и передаю ему модель.

Это не удается, по-видимому, потому что controlContext не установлен.Я получаю эту ошибку:

Значение не может быть нулевым.Имя параметра: controllerContext Описание: необработанное исключение произошло во время выполнения текущего веб-запроса.Пожалуйста, просмотрите трассировку стека для получения дополнительной информации об ошибке и о том, где она возникла в коде.

Сведения об исключении: System.ArgumentNullException: значение не может быть нулевым.Имя параметра: controllerContext

Итак, как мне вручную создать экземпляр IController в коде, чтобы «все» работало?

Заранее спасибо.

Так зачем мне это нужно? Я играю с некоторыми идеями архитектуры и игровой логики для "онлайн-стратегии".

У меня есть приложение ASP.NET MVC 4 (Preview), которое является моей веб-версией игры.Идея заключается в том, что в игру также следует играть на таких устройствах, как Windows Phone, iPhone и т. Д. Через приложения NATIVE.Поэтому мне нужен некоторый API для моей игры (какой-то REST-сервис, который общается через http / json).Поскольку этот API будет общедоступным интерфейсом для игры, вся логика игры, конечно же, будет находиться в стороне от этого API.

Поэтому я хочу использовать этот API как для «веб-версии», так и для «мобильной»версия "игры.Я реализовал этот API как область внутри ASP.NET MVC 4 (предварительная версия).Сначала я должен был сделать httpwebrequest от моей «веб-версии» до API, поэтому я использовал API ТОЧНО, как и «мобильная версия».Но потом я подумал, что было бы лучше на самом деле просто инстанцировать контроллеры вручную, чтобы избежать всех накладных расходов на json / web-вызовы, которые я получил бы от вызова API «правильным способом».

Так вот почему яЯ здесь, сейчас я хочу создать экземпляр моих контроллеров вручную в коде, потому что я хочу использовать в них точную логику.

Имеет смысл?Если у вас есть идея получше, пожалуйста, дайте мне знать - я делаю это для изучения этого, а не для производства реального продукта - по крайней мере, сейчас это не цель - сейчас я просто пытаюсь изучить некоторые новые вещи:)

1 Ответ

0 голосов
/ 12 января 2012

Вам не нужно звонить ValidateModel напрямую.

По крайней мере, мне никогда не нужно было вызывать его напрямую в каком-либо коде, и я не видел ни одного примера, который бы тоже вызывал его.

Вы можете использовать атрибуты System.ComponentModel.DataAnnotations, чтобы контролировать, как проверяется ваша модель.

Позвольте мне привести пример, скопированный из некоторого рабочего кода.

Класс модели:
(В основном просто DTO, ничего особенного.)

public class ArticleModel
{
    public ArticleModel()
    {
        CategoryIds = new List<int>();
    }

    public int Id { get; set; }

    [Required(ErrorMessage = "Field mandatory!")]
    public string Title { get; set; }

    [Required(ErrorMessage = "Field mandatory!")]
    public string Text { get; set; }

    public string Summary { get; set; }

    public bool RefreshDate { get; set; }

    public List<int> CategoryIds { get; set; }
}

Действие контроллера:
(Создает объект для ORM и сохраняет его в базе данных.)

[HttpPost]
[ValidateInput(false)]
[SiteAuthorize(SiteAuthorization.SiteOwner)]
public ActionResult EditArticle(ArticleModel model)
{
    var article = Repository.Retrieve<Article>().SingleOrDefault(x => x.Id == model.Id && x.Site == ColorfulUtility.CurrentSite);

    if (article == null)
        return RedirectToAction("ArticleList");

    if (ModelState.IsValid)
    {
        if (model.RefreshDate)
            article.Date = DateTime.Now;

        article.Title = model.Title.SimpleTextToSafeHtml();
        article.Text = model.Text.RichTextToSafeHtml();
        article.Summary = model.Summary.RichTextToSafeHtml();

        foreach (var category in ColorfulUtility.CurrentSite.ArticleCategories)
        {
            if (!article.Categories.Contains(category) && model.CategoryIds.Contains(category.Id))
            {
                article.Categories.Add(category);
            }
            else if (article.Categories.Contains(category) && !model.CategoryIds.Contains(category.Id))
            {
                article.Categories.Remove(category);
            }
        }

        Repository.Flush();

        return RedirectToAction("ArticleList");
    }

    return View("CreateArticle", model);
}
...