简体   繁体   English

ASP.NET MVC和WCF

[英]ASP.NET MVC and WCF

I'm working my way into MVC at the moment, but on my "To learn at some point" list, I also have WCF. 我现在正在进入MVC,但在我的“要在某些方面学习”列表中,我也有WCF。

I just wonder if WCF is something that should/could be used in an MVC Application or not? 我只是想知道WCF是否应该/可以在MVC应用程序中使用? The Background is that I want a Desktop Application (.NET 3.5, WPF) interact with my MVC Web Site, and I wonder what the best way to transfer data between the two is. 背景是我希望桌面应用程序(.NET 3.5,WPF)与我的MVC网站交互,我想知道在两者之间传输数据的最佳方法是什么。 Should I just use special Views/have the controllers return JSON or XML (using the ContentResult)? 我应该只使用特殊的视图/让控制器返回JSON或XML(使用ContentResult)?

And maybe even more important, for the other way round, could I just call special controllers? 也许更重要的是,反过来说,我可以打电话给特殊控制器吗? Not sure how Authorization would work in such a context. 不确定授权如何在这样的环境中起作用。 I can either use Windows Authentication or (if the Site is running forms authentication) have the user store his/her credentials in the application, but I would then essentially create a HTTP Client in my Application. 我可以使用Windows身份验证或(如果站点正在运行表单身份验证)让用户将他/她的凭据存储在应用程序中,但我基本上会在我的应用程序中创建一个HTTP客户端。 So while MVC => Application seems really easy, Application => MVC does seem to be somewhat tricky and a possible use for WCF? 所以虽然MVC => Application看起来很简单,但是Application => MVC似乎有点棘手并且可能用于WCF?

I'm not trying to brute-force WCF in this, but I just wonder if there is indeed a good use case for WCF in an MVC application. 我不是试图在这里强制使用WCF,但我只是想知道在MVC应用程序中是否确实存在WC​​F的良好用例。

WCF services might make sense in this situation, but don't create services that align with your UI, create services that align with the business processes. 在这种情况下,WCF服务可能有意义,但不要创建与UI一致的服务,创建与业务流程一致的服务。 ie. 即。 you won't have a service that returns the view data for each page, you will have a service that exposes logical operations. 如果您没有返回每个页面的视图数据的服务,您将拥有一个公开逻辑操作的服务。 Then, your site can call the same services that the windows client calls, but you don't have to couple the design of the windows client to the design of the web site. 然后,您的站点可以调用Windows客户端调用的相同服务,但您不必将Windows客户端的设计与网站的设计相结合。

Instead of this: 而不是这个:

Windows Client -> Services -> Web Site Windows客户端 - >服务 - >网站

It should be: 它应该是:

Windows Client -> Services Windows客户端 - >服务

Web Site -> Services 网站 - >服务

You could use ADO.NET Data Services to share your data with either JSON (for JavaScript clients) or XML (for desktop applications). 您可以使用ADO.NET Data Services与JSON(适用于JavaScript客户端)或XML(适用于桌面应用程序)共享数据。

ASP.NET MVC can then take advantage of this by using either of two in the model. 然后,ASP.NET MVC可以通过在模型中使用两个中的任何一个来利用它。 As you probably know, ADO.NET Data Services is based on WCF so you were on the right track. 您可能知道,ADO.NET数据服务基于WCF,因此您处于正确的轨道上。

I use asp.net mvc as both my html website (default view engine) and my service endpoint. 我使用asp.net mvc作为我的html网站(默认视图引擎)和我的服务端点。 The service endpoint is used by my WPF and Silverlight clients by injecting "content-type=text/xml" into the header of a WebClient request (see ScottGu's post on consuming a service in SL which inspired this approach). 我的WPF和Silverlight客户端使用服务端点,将“content-type = text / xml”注入WebClient请求的标头中(请参阅ScottGu关于在SL中使用服务的帖子 ,这启发了这种方法)。 I found somewhere on the net, some code that overrides the OnActionExecuted event like this: 我在网上找到了某个地方,一些代码覆盖了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
            };
        }
    }
}

So, the commented out piece is the code that I found - see the stackoverflow links for where I got it :) 所以,注释掉的部分是我找到的代码 - 请参阅stackoverflow链接以获取它的位置:)

I overrode the ToString() method on all of my business objects to return string representing how the business object would like to represent itself as xml. 我覆盖了所有业务对象上的ToString()方法,返回表示业务对象如何将自己表示为xml的字符串。 WCF accomplishes this via attributes, but I wanted a cleaner solution that didn't rely on reflection AND I didn't want to have both a website project and a WCF project - the problem with two projects is that it was hard to keep them both in sync with respect to functionality - I would get requests like "why doesn't the service allow me to filter my results like the website does?" WCF通过属性实现了这一点,但是我想要一个不依赖于反射的更清洁的解决方案而且我不想同时拥有一个网站项目和一个WCF项目 - 两个项目的问题在于它们很难保持它们两者在功能方面同步 - 我会收到诸如“为什么服务不允许我像网站一样过滤我的结果?”的请求。

I'm very interested in other's feedback on this approach :) 我对其他人对此方法的反馈非常感兴趣:)

Here's an example of a business object: 以下是业务对象的示例:

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);
    }
}

You could use OData for your MVC application to handle Xml/Json type stuff. 您可以使用OData为您的MVC应用程序处理Xml / Json类型的东西。 I know other people have suggested roll your own - and this is what I'm currently doing .. via the use of my own custom ActionFilter or custom ViewResult. 我知道其他人建议自己动手 - 这就是我目前正在做的......通过使用我自己的自定义ActionFilter或自定义ViewResult。

Sample OData code: Scott Hanselman's OData + StackOverflow blog post . 示例OData代码: Scott Hanselman的OData + StackOverflow博客文章

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM