asp.net mvc colocou controladores em um projeto separado

107

Estou apenas aprendendo asp.net mvc e estou tentando descobrir como mover meus controladores para um projeto separado. Normalmente, quando eu projetei aplicativos da web asp.net antes, criei um projeto para meus modelos, outro para minha lógica e, em seguida, havia a web.

Agora que estou aprendendo o asp.net mvc, esperava seguir um padrão semelhante e colocar os modelos e controladores em seus próprios projetos separados e apenas deixar as visualizações / scripts / css na web. A parte de modelos foi fácil, mas o que eu não entendo é como fazer meus controladores em um projeto separado serem "encontrados". Além disso, gostaria de saber se isso é aconselhável. Obrigado!

Aaron Palmer
fonte

Respostas:

92

Em primeiro lugar, certamente é uma boa ideia colocar seu modelo em um projeto separado. Como você descobriu, isso é trivial.

Com relação a controladores e visualizações, não vejo nenhuma vantagem óbvia em separá-los para a maioria dos projetos básicos, embora você possa ter uma necessidade específica de fazê-lo em um aplicativo específico.

Se você decidir fazer isso, precisará informar ao framework como encontrar seus controladores. A maneira básica de fazer isso é fornecendo seu próprio ControllerFactory. Você pode dar uma olhada no código-fonte da DefaultControllerFactory para ter uma ideia de como isso é feito. Subtipar esta classe e substituir o método GetControllerType (string controllerName) pode ser o suficiente para realizar o que você está pedindo.

Depois de criar seu próprio ControllerFactory personalizado, você adiciona a seguinte linha a Application_Start em global.asax para informar ao framework onde encontrá-lo:

ControllerBuilder.Current.SetControllerFactory(new MyControllerFactory());

Atualização: Leia esta postagem e as postagens vinculadas a ela para obter mais informações. Veja também o comentário de Phil Haack nessa postagem sobre:

ControllerBuilder.Current.DefaultNamespaces.Add(
    "ExternalAssembly.Controllers");

... que não é uma solução completa, mas possivelmente boa o suficiente para casos simples.

Craig Stuntz
fonte
2
Obrigado Craig! Isso é exatamente o que estou procurando. Essa informação existe na web? Procurei no Google por tudo, sem muita sorte. StackOverflow surge novamente!
Aaron Palmer
11
Eu concordo, os controladores lidam com a entrada do usuário, manipulam o modelo e, em seguida, passam os dados para a visualização. Eles são normalmente muito específicos para um aplicativo. Qualquer lógica que não seja específica do aplicativo pode ser melhor em uma biblioteca ou modelo. Mas os controladores em geral devem estar com o projeto da web.
Haacked em
2
Eu tenho um controlador de erro e visualizações idênticas entre dois aplicativos. Faz sentido para mim tê-los em uma única montagem que ambos os aplicativos possam usar.
Sailing Judo
3
Não é mais fácil testar os controladores e usar IoC quando os controladores estão em um projeto separado - esse seria o principal motivo
Samuel G
1
@Chev, acho que não faz diferença. A testabilidade de seus controladores tem mais a ver com como você os codifica , não onde eles moram.
Craig Stuntz de
19

Embora seja razoável criar seu próprio ControllerFactory, achei mais conveniente definir todos os meus controladores em cada projeto, mas derivá-los dos controladores em meu projeto compartilhado:

namespace MyProject1.Controllers
{
   public class MyController : MySharedProject.Controllers.MyController
   {
      // nothing much to do here...
   }
}

namespace MySharedProject.Controllers
{
   public abstract class MyController : System.Web.Mvc.Controller
   {
      // all (or most) of my controller logic here...
   }
}

A vantagem adicional é que você tem um local para colocar a lógica do controlador que difere de projeto para projeto. Além disso, é mais fácil para outros desenvolvedores encontrarem rapidamente a lógica do seu controlador porque os controladores existem no local padrão.

Sobre se isso é aconselhável, acho que sim. Eu criei uma lógica comum de gerenciamento de contas que desejo compartilhar entre projetos que, de outra forma, têm uma lógica de negócios muito diferente. Portanto, estou compartilhando minha conta e os controladores administrativos, mas os outros controladores são específicos para seus respectivos projetos.

Esse cara
fonte
1
Funcionou muito bem, mas tive que eliminar algum código redundante para evitar um erro de roteamento
Ken Mc
Oi, como posso gerenciar o roteamento neste tipo de projeto? eu quero usar o roteamento de atributo ...
محمد
Você pode usar o roteamento de atributo como faria normalmente.
ThisGuy
2
Não sei por que isso não tem mais votos positivos ... muito mais elegante do que a resposta aceita, eu acho. Obrigado!
jleach
Isso não funciona para mim. Você poderia dizer que é .Net Core ou .Net Framework?
Homayoun Behzadian
4
  • Adicione a biblioteca de classes para seu projeto mvc.
  • Na classe, adicione o seguinte código (para código do controlador u'r)

    namespace ContactController
    {
    public class ContactController : Controller
    {
        public ActionResult Call()
        {
            ViewBag.Title = "Inside MyFirst Controller.";
            return View();
        }
    }

    }

  • Na pasta de visualização do projeto mvc, adicione a pasta para Contato e crie um arquivo Call.cshtml. Ver pasta

  • Adicione a referência do projeto da biblioteca de classes ao seu projeto MVC principal.

Referência

  • Finalmente, para consultar o namespace do controlador de contato no Route Config.

RouteConfig

RandyMohan
fonte
3
É um pouco lamentável que você tenha um namespace com o mesmo nome do controlador.
Mariusz Jamro
3

Meu problema foi resolvido depois que atualizei a System.Web.Mvcreferência do NuGet, para que MvcWebsite e Class Library usem a mesma System.Web.Mvcversão

Não há necessidade de adicionar namespaces padrão

Homayoun Behzadian
fonte
O problema era que MvcWebsite não lançou exceção enquanto o assembly mvc presente tem uma versão inferior ao assembly mvc referenciado da biblioteca de classes
Homayoun Behzadian
1

A forma mais simples de separação que uso é reter as Visualizações "como estão" no projeto MVC original, mas remover os Controladores. Em seguida, em um novo projeto ClassLibrary, adicione as classes Controller e garanta que sejam herdadas do Controller.

O mecanismo de roteamento MVC será roteado automaticamente para os controladores na ClassLibrary e os controladores construirão automaticamente as visualizações do projeto MVC original, desde que você tenha suas referências e usos corretamente no lugar.

Estou usando essa arquitetura para implementar um módulo de relatórios Html que pode ser compilado e implantado separadamente da solução principal. Finalmente estou livre do SSRS!

Jamie
fonte