2008-10-19 30 views
27

Estoy trabajando en MVC por el momento, pero en mi lista "Para aprender en algún momento", también tengo WCF.ASP.NET MVC y WCF

Me pregunto si WCF es algo que debería/podría usarse en una aplicación MVC o no? El trasfondo es que quiero que una aplicación de escritorio (.NET 3.5, WPF) interactúe con mi sitio web de MVC, y me pregunto cuál es la mejor forma de transferir datos entre los dos. ¿Debería usar vistas especiales/hacer que los controladores devuelvan JSON o XML (usando ContentResult)?

Y tal vez lo más importante, para el revés, ¿podría simplemente llamar a los controladores especiales? No estoy seguro de cómo funcionaría la Autorización en dicho contexto. Puedo usar la Autenticación de Windows o (si el Sitio está ejecutando autenticación de formularios) que el usuario almacene sus credenciales en la aplicación, pero básicamente crearía un Cliente HTTP en mi Aplicación. Entonces, aunque la aplicación MVC => parece realmente fácil, Application => MVC parece ser un poco complicado y un posible uso de WCF?

No estoy tratando de usar fuerza bruta WCF en esto, pero me pregunto si realmente hay un buen caso de uso para WCF en una aplicación MVC.

Respuesta

47

Los servicios de WCF pueden tener sentido en esta situación, pero no creen servicios que se alineen con su UI, creen servicios que se alineen con los procesos de negocios. es decir. no tendrá un servicio que devuelva los datos de vista para cada página, tendrá un servicio que expone las operaciones lógicas. Luego, su sitio puede llamar a los mismos servicios que el cliente de Windows llama, pero no tiene que acoplar el diseño del cliente de Windows con el diseño del sitio web.

lugar de esto:

cliente de Windows -> Servicios -> Sitio Web

que debe ser:

cliente de Windows -> Servicios

Sitio Web -> Servicios

+0

Me tomó algo de tiempo entender esto realmente, pero tiene sentido. WCF como servidor de servicios para múltiples clientes, mvc como un sitio web que traduce las llamadas de servicio a s ui. –

9

Puede utilizar ADO.NET Data Services para compartir sus datos con JSON (para clientes de JavaScript) o XML (para aplicaciones de escritorio).

ASP.NET MVC puede aprovechar esto utilizando cualquiera de los dos en el modelo. Como probablemente sepa, ADO.NET Data Services se basa en WCF por lo que estaba en el camino correcto.

8

Utilizo asp.net mvc como mi sitio web html (motor de vista predeterminado) y mi punto final de servicio. El punto final del servicio es utilizado por mis clientes de WPF y Silverlight al inyectar "content-type = text/xml" en el encabezado de una solicitud de WebClient (ver ScottGu's post al consumir un servicio en SL que inspiró este enfoque). He encontrado en algún lugar de la red, un código que anula el evento OnActionExecuted así:

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

Así, la pieza comentada es el código que he encontrado - vea los enlaces para stackoverflow donde lo tengo :)

Anulé el método ToString() en todos mis objetos comerciales para devolver una cadena que representa cómo el objeto comercial desea representarse a sí mismo como xml. WCF logra esto a través de atributos, pero yo quería una solución más limpia que no dependiera de la reflexión Y no quería tener un proyecto de sitio web y un proyecto de WCF. El problema con dos proyectos es que era difícil mantenerlos a ambos en sincronía con respecto a la funcionalidad: recibiría solicitudes como "¿por qué el servicio no me permite filtrar mis resultados como lo hace el sitio web?"

estoy muy interesado en la regeneración del otro en este enfoque :)

He aquí un ejemplo de un objeto de negocio:

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

Usted podría utilizar OData para su aplicación MVC para manejar XML/JSON escriba cosas. Sé que otras personas han sugerido rodar la suya, y esto es lo que estoy haciendo actualmente ... mediante el uso de mi propio ActionFilter personalizado o ViewResult personalizado.

Código de muestra OData: Scott Hanselman's OData + StackOverflow blog post.