API da Web na solução MVC em projeto separado

88

Estou criando um novo projeto MVC4, e pesquisas me levaram a acreditar que a comunicação de javascript para o lado do servidor é melhor alcançada agora por meio da estrutura de API da web em vez de ações de controlador. Meu entendimento está correto sobre isso?

Estou presumindo que posso compartilhar todos os meus atributos, etc, entre a API da web e os controladores MVC, então, na verdade, não parece uma grande mudança para mim.

Quando estou configurando aplicativos, gosto de dividir os componentes em projetos. Meu plano era ter um projeto MVC e um projeto de API web. Mas eu tive problemas. Por exemplo, acabei com 2 aplicativos como tal, roteamento separado configurado, etc. etc.

Portanto, minha pergunta é: em um aplicativo MVC, a estrutura da API da web deve estar no mesmo projeto ou a API da web deve ser separada em um projeto próprio e contornar os problemas?

amador
fonte

Respostas:

110

Infelizmente, você está errado sobre isso - presumo que posso compartilhar todos os meus atributos etc. entre a API da web e os controladores de mvc, então, aparentemente, não parece uma grande mudança para mim.

Muitos dos conceitos usados ​​pela API da Web e MVC, embora semelhantes à primeira vista, na verdade não são compatíveis. Por exemplo, os atributos da API da Web são System.Web.Http.Filters.Filtere os atributos MVC são System.Web.Mvc.Filter- e não são intercambiáveis.

O mesmo se aplica a muitos outros conceitos - vinculação de modelo (mecanismos completamente diferentes), rotas (a API da Web usa HTTPRoutes e não Rotas, embora ambos operem na mesma RouteTable subjacente), resolvedor de dependências (não compatível) e muito mais - embora semelhante no superfície, são muito diferentes na prática. Além disso, a API Web não possui um conceito de áreas.

Em última análise, se tudo o que você está tentando alcançar é ter uma maneira "nova e moderna" de fornecer conteúdo JSON - pense duas vezes antes de seguir esse caminho. Eu certamente não recomendaria refatorar qualquer código existente, a menos que você realmente esteja pensando em abraçar HTTP e construir seu aplicativo de uma forma RESTful.

Tudo realmente depende do que você está construindo. Se você está iniciando um novo projeto e tudo que você precisa é servir algum JSON para facilitar seu aplicativo da web - desde que você esteja disposto a viver com algum código potencialmente duplicado (como o que mencionei acima), a API da Web pode ser facilmente hospedada dentro o mesmo projeto da ASP.NET MVC.

Eu só separaria a API da Web em um projeto separado se você for construir uma API adequada para seu serviço online - talvez para ser consumida por clientes externos ou por vários dispositivos - como abastecer seus aplicativos móveis.

Filip W
fonte
2
+1 Excelente resposta. Achei inicialmente que tanto o MVC quanto o WebAPI podem compartilhar parte do código, especialmente no caso de filtros, vinculação de modelo, etc., mas eles são totalmente diferentes.
VJAI de
5
Sim, em tal cenário, basta iniciar um novo projeto MVC4 no Visual Studio e, quando solicitado por um modelo de projeto (segunda tela), simplesmente selecione Web API. Isso instalará a API da Web do Nuget e, no caso que você descreveu, deve funcionar perfeitamente. O que você obtém é um arquivo de configuração de API da Web separado conectado a Global.asax. Além disso, você pode querer separar os controladores de API em uma pasta separada (por padrão, eles estão juntos com os controladores MVC). Finalmente, as rotas padrão são obviamente configuradas separadamente e não interferem umas nas outras
Filip W
9
Eu gostaria que meu líder tivesse lido este post antes de projetar nosso projeto atual.
Billdr
2
@FilipW Obrigado por boas explicações. Eu também tenho um aplicativo MVC e usarei WebAPI2 para usar o serviço para aplicativos Android. Por outro lado, como David Peden diz abaixo, segurança, manutenção e implantação também são muito importantes ao decidir criar um novo projeto separado para WebAPI. Nesse caso, lembrando-se deles, o que você sugere? Para criar um novo projeto separado para WebAPI ou usar o projeto MVC atual? Desde já, obrigado.
Jack
1
Muito bom "Eu só separaria a API da Web em um projeto separado se você fosse construir uma API adequada para seu serviço online - talvez para ser consumida por clientes externos ou por vários dispositivos - como abastecer seus aplicativos móveis." acertar o prego na cabeça e torna mais fácil determinar como fazê-lo.
ozzy432836
27

IMO, segurança e implantação devem orientar sua decisão. Por exemplo, se seu aplicativo MVC usa autenticação de formulários, mas você está interessado em usar autenticação básica (com SSL) para sua API, projetos separados irão tornar sua vida mais fácil. Se você deseja hospedar seu site em www.example.com, mas hospedar sua API como api.example.com (em vez de www.example.com/api), projetos separados tornarão sua vida mais fácil. Se você separar seus projetos e subdominá-los de acordo e pretende alavancar sua própria API de seu aplicativo MVC, você terá que descobrir como lidar com o problema da política da mesma origem para chamadas do lado do cliente para sua API. Soluções comuns para isso são aproveitar jsonp ou CORS (de preferência, se você puder).

Atualização (26/03/2013): Suporte oficial para CORS chegando: http://aspnetwebstack.codeplex.com/wikipage?title=CORS%20support%20for%20ASP.NET%20Web%20API

David Peden
fonte
Estou tentando entender os problemas em torno da decisão de integrar a API da Web ao meu aplicativo MVC ou tê-lo como um projeto separado. Consegui implantar com sucesso um aplicativo Web API HelloWorld em um subdomínio em meu host da web. A partir deste projeto separado, provavelmente estarei usando o modelo do meu aplicativo da web MVC e chamando o código nesse projeto separado. Parece que seria mais fácil seguir esse caminho de um projeto separado, mas que problemas você acha que eu poderia encontrar com essa abordagem?
Ciaran Gallagher
2
Pessoalmente, eu não usaria seu modelo de visualização como seu DTO para sua API. Eu esperaria que essa decisão causasse sérios problemas no caminho, já que seus modelos de visualização e assinaturas de API divergem. SoC ( en.wikipedia.org/wiki/Separation_of_concerns ) é muito importante.
David Peden
@DavidPeden Você sugere criar um novo projeto separado para WebAPI. Isso é verdade? Por outro lado, vou criar um novo projeto separado para WebAPI (atualmente tenho uma camada de interface do usuário (MVC) e uma camada de dados (biblioteca de classes) em meu aplicativo. Então, eu também uso DI, mas estou me perguntando se posso usar as mesmas Entidades, Repositórios, Interfaces e classes abstratas na Camada de Dados para o projeto WebAPI recém-criado e a única coisa que tenho que fazer é criar Controladores WebAPI? Ou também crio todos eles (Entidades, Repositórios, Interfaces e Resumo aulas) novamente para o WebAPI? Alguma ajuda, por favor?
Jack
1
@ H.Johnson É difícil dar conselhos gerais que sejam significativos, mas parece que você se beneficiaria em ter uma camada de serviço de aplicativo que encapsula suas entidades e repositórios que podem ser aproveitados por ambas as interfaces de usuário (MVC e API).
David Peden
9

Depois de algum grau de experiência (criação de API para apps e para mvc). Eu principalmente faço ambos.

Eu crio um projeto separado para chamadas de API que vêm de outros clientes ou outros dispositivos (aplicativos Android / IOS). Um dos motivos é porque a autenticação é diferente, é baseada em tokens (para mantê-la sem estado). Não quero misturar isso no meu aplicativo MVC.

Para minhas chamadas de api javascript / jquery para meu aplicativo mvc, gosto de manter as coisas simples, então incluo uma api da web dentro do meu aplicativo MVC. Não pretendo ter autenticação baseada em token com minhas chamadas de api javascript, porque hey, está no mesmo aplicativo. Posso apenas usar o [authorize]atributo em um endpoint de API, quando um usuário não estiver logado, ele não obterá os dados.

Além disso, ao lidar com carrinhos de compras e você deseja armazenar o carrinho de compras de um usuário em uma sessão (enquanto não estiver conectado), você também precisa ter isso em sua API se adicionar / excluir produtos por meio de seu código javascript. Isso tornará sua API com estado, com certeza, mas também reduzirá a complexidade em sua MVC-API.

CularBytes
fonte
4
Bem @Dimi, que edição inútil para obter alguns votos ... Como posso rejeitar estes?
CularBytes
Faça o que você quiser. Eu edito não por votos, mas para ter a melhor aparência, presumo. Continue.
Desenvolvedor
3
@CularBytes Você não pode rejeitar edições, mas pode editá-las novamente e reverter as alterações. Isso requer um processo de revisão por pares com menos de 2.000 repetições, mas você tem representantes suficientes para fazer isso instantaneamente. Concordo que a edição não adicionou nenhum valor e a reverti para você.
Dan Bechard
5

Recentemente, fiz quase a mesma coisa: comecei com um novo projeto de aplicativo da web MVC 4 escolhendo o modelo de API da Web no VS2012.

Isso criará uma API da Web hospedada no mesmo aplicativo que o MVC.

Eu queria mover os ApiControllers para um projeto de biblioteca de classes separado. Isso foi bastante fácil, mas a solução estava um pouco escondida.

Em AssemblyInfo.cs do projeto MVC 4, adicione uma linha de código semelhante

[assembly: PreApplicationStartMethod(typeof(LibraryRegistrator), "Register")]

Agora você precisa da classe LibraryRegistrator (sinta-se à vontade para nomeá-la como quiser)

public class LibraryRegistrator
    {
        public static void Register()
        {
            BuildManager.AddReferencedAssembly(Assembly.LoadFrom(HostingEnvironment.MapPath("~/bin/yourown.dll")));
        }
    }

No projeto MVC 4, também adicione referência à biblioteca Api.

Agora você pode adicionar controladores Api à sua própria biblioteca de classes separada (yourown.dll).

fanvabra
fonte
2

Mesmo se o seu projeto for tão complexo a ponto de justificar dois "front ends", eu ainda consideraria dividir o webapi em um projeto separado como último recurso. Você terá dores de cabeça de implantação e será difícil para um novato entender a estrutura de sua solução. Sem mencionar problemas de roteamento.

Meu objetivo seria manter o namespace system.web isolado em uma "camada de apresentação". Apesar do webapi não ser de apresentação, ele ainda faz parte da interface de seu aplicativo. Contanto que você mantenha a lógica em seu domínio e não em seus controladores, você não deve ter muitos problemas. Além disso, não se esqueça de fazer uso de Areas.

usuario
fonte
1
Meu principal raciocínio para querer projetos separados é que a API não é realmente um front end. É uma camada intermediária.
Lordcheeto,
6
"Seria difícil para um novato entender" não é um grande motivo para escolher uma abordagem em vez de outra. Mantenha a simplicidade quando possível, com certeza, mas as necessidades complexas geralmente exigem soluções complexas. Em vez de escrever código burro para atender aos novatos, devemos treinar novatos para entender e escrever código inteligente.
Dan Bechard
0

Além de configurar a DLL separada para o Web.Api.

Apenas uma sugestão:

  1. Crie o Projeto
  2. Nugget WebActivatorEx
  3. Crie um método de classe a ser chamado em app_start

    [assembly: WebActivatorEx.PostApplicationStartMethod (typeof (API.AppWebActivator), "Start")]

    [assembly: WebActivatorEx.ApplicationShutdownMethod (typeof (API.AppWebActivator), "Shutdown")]

  4. Registre uma rota web.api dentro do método inicial

    public static void Start () {GlobalConfiguration.Configure (WebApiConfig.Register); }

  5. Referencie o projeto ao projeto da Web. para ativar o método inicial.

Espero que isto ajude.

Jayson.centeno
fonte
0

Tentei dividir os controladores de API em um novo projeto. Tudo o que fiz foi criar um novo projeto de biblioteca, movi os controladores dentro da pasta chamada API. Em seguida, adicionou a referência do projeto de biblioteca ao projeto MVC.

A configuração da webAPI é deixada no próprio projeto MVC. Funciona bem.

Jaicind
fonte