ASP.NET MVC et WCF
Je me fraye un chemin dans MVC en ce moment, mais sur ma liste "apprendre à un moment donné", j'ai aussi WCF.
Je me demande juste si WCF est quelque chose qui devrait / pourrait être utilisé dans une Application MVC ou non? L'arrière-plan est que je veux qu'une Application de bureau (. net 3.5, WPF) interagisse avec mon Site Web MVC, et je me demande Quelle est la meilleure façon de transférer des données entre les deux. Devrais-je simplement utiliser des vues spéciales/faire en sorte que les contrôleurs renvoient JSON ou XML (en utilisant ContentResult)?
Et peut-être encore plus important, dans l'autre sens, pourrais-je simplement appeler des contrôleurs Spéciaux? Je ne sais pas comment L'autorisation fonctionnerait dans un tel contexte. Je peux soit utiliser L'authentification Windows ou (si le Site exécute l'authentification de formulaires) demander à l'utilisateur de stocker ses informations d'identification dans l'application, mais je créerais alors essentiellement un client HTTP dans mon Application. Donc, alors que MVC = > Application semble vraiment facile, Application = > MVC semble être un peu délicat et une utilisation possible pour WCF?
Je n'essaie pas de forcer WCF en cela, mais je me demande juste s'il y a effectivement un bon cas d'utilisation pour WCF dans une application MVC.
4 réponses
Les services WCF peuvent avoir du sens dans cette situation, mais ne créez pas de services qui s'alignent sur votre interface utilisateur, créez des services qui s'alignent sur les processus métier. IE. vous n'aurez pas de service qui renvoie les données de vue pour chaque page, vous aurez un service qui expose les opérations logiques. Ensuite, votre site peut appeler les mêmes services que les appels du client windows, mais vous n'avez pas à coupler la conception du client windows à la conception du site web.
Au lieu de ceci:
Client Windows -> Services - > Site Web
Il devrait être:
Client Windows - > Services
Site Web - > Services
Vous pourriez utiliser ADO.NET Services de données pour partager vos données avec JSON (pour les clients JavaScript) ou XML (pour les applications de bureau).
ASP.NET MVC peut alors en profiter en utilisant l'un des deux dans le modèle. Comme vous le savez probablement, ADO.NET Data Services est basé sur WCF donc vous étiez sur la bonne voie.
J'utilise asp.net mvc en tant que mon site Web html (moteur de vue par défaut) et mon point de terminaison de service. Le point de terminaison de service est utilisé par mes clients WPF et Silverlight en injectant "content-type = text / xml" dans l'en-tête d'une requête WebClient (voir post de ScottGu sur la consommation d'un service dans SL qui a inspiré cette approche). J'ai trouvé quelque part sur le net, du code qui remplace L'événement OnActionExecuted comme ceci:
public class JsonOrXml : ActionFilterAttribute
{
private static UTF8Encoding UTF8 = new UTF8Encoding(false);
public override void OnActionExecuted(ActionExecutedContext filterContext)
{
// setup the request, view and data
HttpRequestBase request = filterContext.RequestContext.HttpContext.Request;
ViewResult view = (ViewResult)(filterContext.Result);
var data = view.ViewData.Model;
String contentType = request.ContentType ?? string.Empty;
// JSON
if (contentType.Contains("application/json") || (string)view.ViewData["FORMAT"] == "json")
{
filterContext.Result = new JsonResult
{
Data = data
};
}
// POX
else if (contentType.Contains("text/xml") || (string)view.ViewData["FORMAT"] == "xml")
{
// MemoryStream to encapsulate as UTF-8 (default UTF-16)
// http://stackoverflow.com/questions/427725/
//
// MemoryStream also used for atomicity but not here
// http://stackoverflow.com/questions/486843/
//using (MemoryStream stream = new MemoryStream(500))
//{
// using (var xmlWriter =
// XmlTextWriter.Create(stream,
// new XmlWriterSettings()
// {
// OmitXmlDeclaration = false,
// Encoding = UTF8,
// Indent = true
// }))
// {
// new XmlSerializer(data.GetType()).Serialize(xmlWriter, data);
// }
// filterContext.Result = new ContentResult
// {
// ContentType = "text/xml",
// Content = UTF8.GetString(stream.ToArray()),
// ContentEncoding = UTF8
// };
//}
XmlDeclaration xmlDecl = new XmlDocument().CreateXmlDeclaration("1.0", "UTF-8", "yes");
filterContext.Result = new ContentResult
{
ContentType = "text/xml",
Content = xmlDecl.OuterXml + data.ToString(),
ContentEncoding = UTF8
};
}
}
}
Donc, la pièce commentée est le code que j'ai trouvé-voir le liens stackoverflow pour où je l'ai eu:)
J'ai dépassé la méthode ToString () sur tous mes objets métier pour renvoyer une chaîne représentant la façon dont l'objet métier voudrait se représenter en tant que xml. WCF accomplit cela via des attributs, mais je voulais une solution plus propre qui ne reposait pas sur la réflexion et je ne voulais pas avoir à la fois un projet de site web et un projet WCF - le problème avec deux projets est qu'il était difficile de les synchroniser en ce qui concerne la fonctionnalité - Je obtiendrais des demandes comme " Pourquoi le service ne me permet-il pas de filtrer mes résultats comme le fait le site web?"
Je suis très intéressé par les commentaires des autres sur cette approche:)
Voici un exemple d'objet métier:
public class ContentFile : Entity
{
public ContentBook BelongsToBook { get; set; }
public string FileName { get; set; }
public XElement FileXml { get; set; }
public Binary FileData { get; set; }
public List<ContentFile> Versions { get; set; }
public List<ContentNode> ContentNodes { get; set; }
public override string ToString()
{
return this.ToString(SaveOptions.DisableFormatting);
}
public string ToString(SaveOptions options)
{
XElement xml = XElement.Parse("<contentFile id=\"" + Id.ToString() + "" + "\" />");
xml.Add(new XElement("fileName", FileName));
xml.Add(new XElement("fileStructure", FileXml));
xml.Add(base.ToString(options));
return xml.ToString(options);
}
}
Vous pouvez utiliser OData pour votre application MVC pour gérer des éléments de type Xml/Json. Je sais que d'autres personnes ont suggéré de rouler votre propre-et c'est ce que je fais actuellement .. via l'utilisation de mon propre ActionFilter personnalisé ou ViewResult personnalisé.
Exemple de code OData: OData de Scott Hanselman + StackOverflow blog post .