ASP.NET MVC 和 WCF

Posted

技术标签:

【中文标题】ASP.NET MVC 和 WCF【英文标题】:ASP.NET MVC and WCF 【发布时间】:2010-09-18 01:01:14 【问题描述】:

我目前正在努力进入 MVC,但在我的“在某个时候学习”列表中,我也有 WCF。

我只是想知道 WCF 是否应该/可以在 MVC 应用程序中使用?背景是我想要一个桌面应用程序(.NET 3.5,WPF)与我的 MVC 网站交互,我想知道在两者之间传输数据的最佳方式是什么。我应该只使用特殊视图/让控制器返回 JSON 或 XML(使用 ContentResult)吗?

也许更重要的是,反过来,我可以调用特殊控制器吗?不确定授权在这种情况下如何工作。我可以使用 Windows 身份验证,或者(如果站点正在运行表单身份验证)让用户将他/她的凭据存储在应用程序中,但我基本上会在我的应用程序中创建一个 HTTP 客户端。因此,虽然 MVC => Application 看起来真的很简单,但 Application => MVC 似乎有点棘手并且可能用于 WCF?

我并不是想在这方面暴力破解 WCF,但我只是想知道在 MVC 应用程序中是否确实存在 WCF 的良好用例。

【问题讨论】:

【参考方案1】:

WCF 服务在这种情况下可能有意义,但不要创建与您的 UI 一致的服务,而是创建与业务流程一致的服务。 IE。您将不会有一个返回每个页面的视图数据的服务,您将有一个公开逻辑操作的服务。然后,您的站点可以调用 windows 客户端调用的相同服务,但您不必将 windows 客户端的设计与网站的设计结合起来。

而不是这个:

Windows 客户端 -> 服务 -> 网站

应该是:

Windows 客户端 -> 服务

网站 -> 服务

【讨论】:

我花了一些时间才真正理解这一点,但这是有道理的。 WCF作为多个客户端的服务宿主,mvc作为将服务调用翻译成s ui的网站。【参考方案2】:

您可以使用 ADO.NET 数据服务与 JSON(用于 javascript 客户端)或 XML(用于桌面应用程序)共享您的数据。

ASP.NET MVC 然后可以通过在模型中使用两个中的任何一个来利用这一点。您可能知道,ADO.NET 数据服务基于 WCF,因此您走在了正确的轨道上。

【讨论】:

【参考方案3】:

我使用 asp.net mvc 作为我的 html 网站(默认视图引擎)和我的服务端点。我的 WPF 和 Silverlight 客户端通过将“content-type=text/xml”注入到 WebClient 请求的标头中来使用服务端点(请参阅 ScottGu 的 post 关于在 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://***.com/questions/427725/
            //
            // MemoryStream also used for atomicity but not here
            // http://***.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
            ;
        
    

所以,注释掉的部分是我找到的代码 - 请参阅 *** 链接了解我从哪里得到它:)

我在所有业务对象上覆盖了 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 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);
    

【讨论】:

【参考方案4】:

您可以为您的 MVC 应用程序使用 OData 来处理 Xml/Json 类型的内容。我知道其他人建议你自己动手——这就是我目前正在做的事情……通过使用我自己的自定义 ActionFilter 或自定义 ViewResult。

示例 OData 代码:Scott Hanselman's OData + *** blog post。

【讨论】:

以上是关于ASP.NET MVC 和 WCF的主要内容,如果未能解决你的问题,请参考以下文章

Asp.net mvc和asp.net有啥区别?

ASP.NET MVC 和 Angularjs 与 ASP.NET MVC 和 Reactjs

浅析ASP.NET Webform和ASP.NET MVC

asp.net mvc 问题!

ASP.NET从MVC5升级到MVC6

从 ASP.NET MVC 迁移到 ASP.NET Core MVC