2011-08-04 3 views
0

Je travaille actuellement sur un ensemble d'applications Web MVC3 qui ont beaucoup en commun mais qui sont déployées en tant que paquetages distincts. Une exception est une application d'administration qui est déployée pour chacune des installations. Ils partagent également une base de données et un ensemble d'entités communes.Contrôleur MVC3 et affichage de la réutilisabilité

Les ajouts récents incluaient l'authentification (authentification des formulaires personnalisés), la construction de menus automatisée (utilisant les attributs d'action du contrôleur) et quelques autres écrans. Le problème que j'ai avec ceux-ci est que j'ai dû créer des contrôleurs et des vues dupliqués.

Le meilleur exemple étant le bit d'authentification. Chaque application a maintenant un contrôleur de compte et une vue Authentification qui sont des copies l'une de l'autre. Vous pouvez voir comment cela peut vite devenir un cauchemar de maintenance car il y a plus d'applications ajoutées. Un autre exemple est une vue partagée dans chaque application qui rend un menu (généralement appelé via Html.Action). Cela nécessite également un contrôleur qui a exactement la même apparence dans chacune des applications. J'ai réussi à extraire les détails d'implémentation de l'authentification et de la construction de menus dans un projet partagé appelé XXX.Core.Mvc qui a aussi des extensions htmlHelper communes et tout ce qui est spécifique au web Mvc. Alors maintenant, toutes les vues et contrôleurs dupliqués dans les applications agissent comme des proxies.

Je cherche un bon modèle sur la façon de se débarrasser de ceux-ci afin que les vues et les contrôleurs communs résident dans un projet partagé où ils peuvent être référencés/invoqués. Est-ce que quelqu'un a fait quelque chose comme ça? Pouvez-vous recommander de bons articles ou exemples? Par exemple, comment pointez-vous une action du contrôleur qui renvoie un View ActionResult à une vue dans un projet ou un chemin partagé différent? Comment router par exemple/Compte/Authentifier à un contrôleur dans un projet différent? Quelles sont les implications de déploiement d'une approche?

+0

[Cette publication] (http://blogs.msdn.com/b/webdevtools/archive/2011/01/20/how-to-get-razor-intellisense-for-model-in-a-class- library-project.aspx) semble utile. Essayer de mettre en œuvre maintenant pour avoir des erreurs personnalisées réutilisables. –

Répondre

0

J'ai essayé deux choses. Dans chaque cas, le contrôleur commun et les vues étaient situés dans un assemblage séparé. Pour preuve de concept, j'ai implémenté une gestion commune des erreurs d'application. Donc, à mon point final demande MvC3, global.asax met en œuvre:

protected void Application_Error() 
{ 
    ApplicationErrorHandler.Get().Handle(Server, new HttpResponseWrapper(Response), new HttpContextWrapper(Context)); 
} 

Où gestionnaire d'erreurs d'application est mis en œuvre dans un ensemble séparé:

public class ApplicationErrorHandler 
{ 
    public static ApplicationErrorHandler Get() 
    { 
     return new ApplicationErrorHandler(); 
    } 

    public void Handle(HttpServerUtility server, HttpResponseBase response, HttpContextBase context) 
    { 
     var exception = server.GetLastError(); 
     var httpException = exception as HttpException; 
     response.Clear(); 
     server.ClearError(); 
     var routeData = new RouteData(); 
     routeData.Values["controller"] = "Errors"; 
     routeData.Values["action"] = "Http500"; 
     routeData.Values["exception"] = exception; 
     response.StatusCode = 500; 
     if (httpException != null) 
     { 
      response.StatusCode = httpException.GetHttpCode(); 
      switch (response.StatusCode) 
      { 
       case 403: 
        routeData.Values["action"] = "Http403"; 
        break; 
       case 404: 
        routeData.Values["action"] = "Http404"; 
        break; 
      } 
     } 
     IController errorsController = new ErrorsController(); 
     var rc = new RequestContext(context, routeData); 
     errorsController.Execute(rc); 
    } 
} 

Dans ce même ensemble dans le dossier des contrôleurs réside le ErrorsController et Vues \ Errors contient les 3 vues nécessaires. Http403.cshtml, Http404.cshtml et Http405.cshtml. SO la structure est la même que dans votre projet Mvc3 normal. Cependant, pour que @model support et intelisense fonctionnent, vous aurez également besoin de web.config - une copie du fichier de Views dans votre projet normal et placé sous les vues dans cet assembly séparé. Quand une erreur d'application se produit dans notre application (statut HTTP 500 - erreur interne du serveur), le ErrorsController est exécuté et la vue utilisée dans ce cas est Http500.cshtml. Le chemin a regardé en sera:

  • ~ \ Views \ Erreurs \ Http500.cshtml
  • ~ \ View \ Shared \ Http500.cshtml

Afin de fournir le fichier de montage que j'ai essayé deux choses:

Approche un: Implémenter un VirtualPathProvider. Je n'entrerai pas dans les détails, mais le but est d'intégrer les vues cshtml en tant que ressources et de les servir en utilisant VirtualPathProvider et VirtualFile.Le problème avec cette approche est que je n'ai trouvé aucun moyen possible de server également le web.config du dossier Views afin que Razor puisse évaluer la vue. Je pourrais l'obtenir pour récupérer le fichier et le diffuser mais ne pas l'exécuter. Pour expliquer quel était le problème, tenez compte des Http500.cshtml:

@model Exception 
<h3>@MvcHtmlString.Create(Model.Message.Replace(Environment.NewLine, "<br />").Replace("\t", "&nbsp;&nbsp;&nbsp;&nbsp;"))</h3> 
<p>@MvcHtmlString.Create(Model.StackTrace.Replace(Environment.NewLine, "<br />").Replace("\t", "&nbsp;&nbsp;&nbsp;&nbsp;"))</p> 
<input type="hidden" name="serverError" value="true"/> 

Ce qui a été renvoyée est le contenu du fichier plutôt que l'exception évaluée. La raison en est que le fichier web.config du dossier View doit également être servi pour que Razor soit utilisé. Par défaut, le moteur de vue est constitué de formulaires Web (.aspx).

Approche deux: créer un répertoire virtuel dans IIS. Cette approche fonctionne beaucoup mieux parce que les vues ne doivent pas être compilées en tant que ressources, il n'y a pas besoin de virtualisation. Tout ce qui était nécessaire était de créer des erreurs de répertoire virtuel sous le dossier Views dans mon application finale et de le pointer vers où les Views \ Errors de l'assembly commun sont déployées.

Bien sûr, il ne se comporte pas comme un plugin approprié car les fichiers communs doivent être déliés séparément de .dll, mais cela ne me dérange pas trop.

Cependant, si quelqu'un connaît un moyen de faire fonctionner les fichiers virtuels pour Razor, je suis tout ouïe. Bien - tous les yeux vraiment.

Questions connexes