【问题标题】:ASP.NET MVC and WCFASP.NET MVC 和 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 的良好用例。

【问题讨论】:

    标签: .net asp.net-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://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 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 + StackOverflow blog post

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2011-01-08
          • 2011-05-30
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-08-14
          • 1970-01-01
          相关资源
          最近更新 更多