我现在正在进入MVC,但在我的"要在某些方面学习"列表中,我也有WCF.
我只是想知道WCF是否应该/可以在MVC应用程序中使用?背景是我希望桌面应用程序(.NET 3.5,WPF)与我的MVC网站交互,我想知道在两者之间传输数据的最佳方法是什么.我应该只使用特殊的视图/让控制器返回JSON或XML(使用ContentResult)?
也许更重要的是,反过来说,我可以打电话给特殊控制器吗?不确定授权如何在这样的环境中起作用.我可以使用Windows身份验证或(如果站点正在运行表单身份验证)让用户将他/她的凭据存储在应用程序中,但我基本上会在我的应用程序中创建一个HTTP客户端.所以虽然MVC => Application看起来很简单,但是Application => MVC似乎有点棘手并且可能用于WCF?
我不是试图在这里强制使用WCF,但我只是想知道在MVC应用程序中是否确实存在WCF的良好用例.
在这种情况下,WCF服务可能有意义,但不要创建与UI一致的服务,创建与业务流程一致的服务.即.如果您没有返回每个页面的视图数据的服务,您将拥有一个公开逻辑操作的服务.然后,您的站点可以调用Windows客户端调用的相同服务,但您不必将Windows客户端的设计与网站的设计相结合.
而不是这个:
Windows客户端 - >服务 - >网站
它应该是:
Windows客户端 - >服务
网站 - >服务
您可以使用ADO.NET Data Services与JSON(适用于JavaScript客户端)或XML(适用于桌面应用程序)共享数据.
然后,ASP.NET MVC可以通过在模型中使用两个中的任何一个来利用它.您可能知道,ADO.NET数据服务基于WCF,因此您处于正确的轨道上.
我使用asp.net mvc作为我的html网站(默认视图引擎)和我的服务端点.我的WPF和Silverlight客户端使用服务端点,将"content-type = text/xml"注入WebClient请求的标头中(请参阅ScottGu 关于在SL中使用服务的帖子,这启发了这种方法).我在网上找到了某个地方,一些代码覆盖了OnActionExecuted事件,如下所示:
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 }; } } }
所以,注释掉的部分是我找到的代码 - 请参阅stackoverflow链接以获取它的位置:)
我覆盖了所有业务对象上的ToString()方法,返回表示业务对象如何将自己表示为xml的字符串.WCF通过属性实现了这一点,但是我想要一个不依赖于反射的更清洁的解决方案而且我不想同时拥有一个网站项目和一个WCF项目 - 两个项目的问题在于它们很难保持它们两者在功能方面同步 - 我会收到诸如"为什么服务不允许我像网站一样过滤我的结果?"的请求.
我对其他人对此方法的反馈非常感兴趣:)
以下是业务对象的示例:
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 ListVersions { get; set; } public List ContentNodes { get; set; } public override string ToString() { return this.ToString(SaveOptions.DisableFormatting); } public string ToString(SaveOptions options) { XElement xml = XElement.Parse(" "); xml.Add(new XElement("fileName", FileName)); xml.Add(new XElement("fileStructure", FileXml)); xml.Add(base.ToString(options)); return xml.ToString(options); } }