Почему T4MVC пытается запустить действия контроллера из Html.ActionLink?

В моих контроллерах я передаю объект IUnitOfWork (который генерируется из IoC), который затем используется в действиях контроллера для функциональности базы данных (IUnitOfWork передается моему сервисному уровню).

В одном из своих представлений я хочу дать ссылку на /Company/View/<id>, поэтому вызываю следующее:

<li>@Html.ActionLink(company.Name, MVC.Company.View(company.Id))</li>

Это вызывается не из контроллера Company, а из представления в другом контроллере. Проблема, похоже, в том, что MVC.Company.View(company.Id) на самом деле вызывает сам метод CompanyController.View(id). Это плохо по 2 причинам.

1) Поскольку непараметрический конструктор CompanyController никогда не вызывается, UnitOfWork не существует, и, таким образом, когда вызывается действие View(int id), вызовы базы данных действия завершаются с ошибкой NullReferenceException.

2) Даже если IUnitOfWork существует, мое представление не должно запускать вызовы базы данных только для того, чтобы генерировались мои ссылки. Html.ActionLink(company.Name, "View", new { id = company.Id }) не вызывает никаких вызовов базы данных (поскольку метод действия не вызывается), поэтому, насколько я понимаю, tml.ActionLink(company.Name, MVC.Company.View(company.Id)) также не должен вызывать никаких вызовов БД. Это чрезмерные запросы к базе данных, абсолютно бесполезные.

Есть ли причина, по которой T4MVC был создан для такого функционирования?


Изменить: Вот объявления для CompanyController

public partial class CompanyController : MyCustomBaseController
{
    public CompanyController(IUnitOfWork unitOfWork)
    {
    }

    public virtual ActionResult Add(int jobSearchId)
    {
    }

    public virtual ActionResult Edit(int id)
    {
    }

    [HttpPost]
    public virtual ActionResult Edit(Company company, int jobSearchId)
    {
    }

    public virtual ActionResult View(int id)
    {
    }
}

public class MyCustomBaseController: Controller
{
    public MyCustomBaseController()
    {
    }

    public int CurrentUserId { get; set; }
}

person KallDrexx    schedule 22.03.2011    source источник
comment
На самом деле ваше действие никогда не должно вызываться. Не могли бы вы предоставить более подробную информацию о том, как выглядит контроллер вашей компании и как выглядит метод действия? Мне не нужны детали внедрения, а только объявления.   -  person David Ebbo    schedule 22.03.2011
comment
Я добавил контроллер, конструктор и объявления действий, которые используются в этом. Если вы имели в виду что-то другое, дайте мне знать, и я обновлю его. Спасибо!   -  person KallDrexx    schedule 22.03.2011
comment
Кажется, вам не хватает имени метода в действии. Кроме того, не могли бы вы включить MyCustomBaseController и его конструкторы? Моя цель — воспроизвести то, что вы видите в небольшом приложении.   -  person David Ebbo    schedule 22.03.2011
comment
Извините, что неправильно вставил. Я обновил его реальным кодом из моей кодовой базы.   -  person KallDrexx    schedule 23.03.2011
comment
@KallDrexx ActionLink содержит внутри себя текущий контроллер; попробуйте вместо этого RouteLink. Если это сработает, дайте мне знать, и я напишу это как ответ.   -  person George Stocker    schedule 23.03.2011
comment
@George: Нет, использование RouteLink по-прежнему вызывает вызов CompanyController.View()   -  person KallDrexx    schedule 23.03.2011


Ответы (1)


Странно, я не могу воспроизвести эту проблему с кодом выше. Что должно произойти, так это то, что вызов MVC.Company.View(company.Id) заканчивается вызовом переопределения вашего метода действия и никогда не вызывает ваш реальный метод действия.

Чтобы это работало, сгенерированный код должен выглядеть так (сохраняя только важные вещи):

public static class MVC {
    public static Mvc3Application.Controllers.CompanyController Company = new Mvc3Application.Controllers.T4MVC_CompanyController();
}

public class T4MVC_CompanyController: Mvc3Application.Controllers.CompanyController {
    public T4MVC_CompanyController() : base(Dummy.Instance) { }

    public override System.Web.Mvc.ActionResult View(int id) {
        var callInfo = new T4MVC_ActionResult(Area, Name, ActionNames.View);
        callInfo.RouteValueDictionary.Add("id", id);
        return callInfo;
    }
}

Можете ли вы взглянуть на сгенерированный код, чтобы увидеть, отличается ли он? Начните с выполнения «Перейти к определению» в «MVC», что откроет T4MVC.cs (под T4MVC.tt).

person David Ebbo    schedule 22.03.2011
comment
Что ж, это раздражает. По-видимому, он просто никогда не регенерировал CompanyController T4, потому что View() там не было, но все мои другие действия были. Хотелось бы, чтобы это было более автоматически, но явное повторное использование T4, кажется, исправило это, и у меня больше нет сбоев. Пометка как ответ, чтобы поблагодарить вас за помощь в моем идиотизме :) - person KallDrexx; 23.03.2011
comment
Вы можете проверить chirpy.codeplex.com, чтобы узнать, как автоматически запускать T4MVC. - person David Ebbo; 23.03.2011
comment
о круто. Раньше я использовал chirpy для консолидации JS, но не знал, что он может работать с t4. Спасибо! - person KallDrexx; 23.03.2011