Procedimiento para migrar servicios web de ASP.NET con AJAX habilitado a WCF
En este tema se describen los procedimientos para migrar un servicio ASP.NET AJAX básico a un servicio Windows Communication Foundation (WCF) equivalente habilitado para AJAX. Muestra cómo crear una funcionalidad de la versión WCF equivalente de un servicio ASP.NET AJAX. Los dos servicios se pueden usar en paralelo o bien el servicio WCF se puede usar para reemplazar el servicio ASP.NET AJAX.
La migración de un servicio ASP.NET AJAX existente a un servicio AJAX WCF le proporciona las siguientes ventajas:
Puede exponer su servicio de AJAX como un servicio SOAP con una configuración adicional mínima.
Puede beneficiarse de las características WCF, como el seguimiento, etc.
En los procedimientos siguientes se ha supuesto que usa Visual Studio 2012.
El código resultado del procedimiento descrito en este tema se proporciona en el ejemplo que sigue a los procedimientos.
Para obtener más información sobre la exposición de un servicio WCF a través de un punto de conexión habilitado para AJAX, consulte el tema Procedimiento para usar la configuración a fin de agregar un punto de conexión ASP.NET AJAX.
Crear y probar la aplicación de servicio web ASP.NET
Abra Visual Studio 2012.
En el menú Archivo, seleccione Nuevo, Proyecto, Web y, a continuación, seleccione Aplicación de servicio web ASP.NET.
Proporcione un nombre al proyecto
ASPHello
y haga clic en Aceptar.Quite los comentarios de línea en el archivo Service1.asmx.cs que contiene
System.Web.Script.Services.ScriptService]
para habilitar AJAX en este servicio.En el menú Compilar, seleccione Compilar solución.
En el menú Depurar, seleccione Iniciar sin depuración.
En la página web generada, seleccione la operación
HelloWorld
.Haga clic en el botón Invocar en la página de prueba de
HelloWorld
. Debería recibir la siguiente respuesta XML.<?xml version="1.0" encoding="utf-8" ?> <string xmlns="http://tempuri.org/">Hello World</string>
Esta respuesta confirma que ha recibido un servicio de AJAX de ASP.NET que funciona y, en particular, que el servicio ha expuesto un punto de conexión en Service1.asmx/HelloWorld que responde a la solicitud HTTP POST y devuelve XML.
Ahora ya puede convertir este servicio para usar un servicio AJAX WCF.
Para crear una aplicación de servicio de AJAX de WCF equivalente.
Haga clic con el botón derecho en el proyecto ASPHello y seleccione Agregar, Nuevo elemento y, a continuación, Servicio WCF habilitado para AJAX.
Proporcione un nombre al servicio
WCFHello
y haga clic en Agregar.Abra el archivo WCFHello.svc.cs.
En Service1.asmx.cs, copie la siguiente implementación de la operación
HelloWorld
.public string HelloWorld() { return "Hello World"; }
Pegue la implementación que ha copiado de la operación
HelloWorld
en el archivo WCFHello.svc.cs en lugar del código siguiente.public void DoWork() { // Add your operation implementation here return; }
Especifique el atributo
Namespace
para ServiceContractAttribute comoWCFHello
.[ServiceContract(Namespace="WCFHello")] [AspNetCompatibilityRequirements(RequirementsMode=AspNetCompatibilityRequirementsMode.Required)] public class WCFHello { … }
Agregue WebInvokeAttribute a la operación
HelloWorld
y establezca la propiedad ResponseFormatpara devolver Xml. Observe que, si no se establece, el tipo devuelto predeterminado es Json.[OperationContract] [WebInvoke(ResponseFormat=WebMessageFormat.Xml)] public string HelloWorld() { return "Hello World"; }
En el menú Compilar, seleccione Compilar solución.
Abra al archivo WCFHello.svc.cs y, en el menú Depurar, seleccione Iniciar sin depuración.
Ahora el servicio expone un punto de conexión en
WCFHello.svc/HelloWorld
, que responde a las solicitudes HTTP POST. Las solicitudes HTTP POST no se pueden probar desde el explorador, pero los puntos de conexión devuelven XML a continuación de XML.<string xmlns="http://schemas.microsoft.com/2003/10/Serialization/">Hello World</string>
Ahora los puntos de conexión
WCFHello.svc/HelloWorld
yService1.aspx/HelloWorld
son funcionalmente equivalentes.
Ejemplo
El código resultado del procedimiento descrito en este tema se proporciona en el ejemplo siguiente.
//This is the ASP.NET code in the Service1.asmx.cs file.
using System;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Linq;
using System.Web;
using System.Web.Services;
using System.Web.Services.Protocols;
using System.Xml.Linq;
using System.Web.Script.Services;
namespace ASPHello
{
/// <summary>
/// Summary description for Service1.
/// </summary>
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[ToolboxItem(false)]
// To allow this Web Service to be called from script, using ASP.NET AJAX, uncomment the following line.
[System.Web.Script.Services.ScriptService]
public class Service1 : System.Web.Services.WebService
{
[WebMethod]
public string HelloWorld()
{
return "Hello World";
}
}
}
//This is the WCF code in the WCFHello.svc.cs file.
using System;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Activation;
using System.ServiceModel.Web;
namespace ASPHello
{
[ServiceContract(Namespace = "WCFHello")]
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
public class WCFHello
{
// Add [WebInvoke] attribute to use HTTP GET.
[OperationContract]
[WebInvoke(ResponseFormat=WebMessageFormat.Xml)]
public string HelloWorld()
{
return "Hello World";
}
// Add more operations here and mark them with [OperationContract].
}
}
El tipo XmlDocument no es compatible con DataContractJsonSerializer porque no es serializable por XmlSerializer. Puede utilizar un tipo XDocument o serializar DocumentElement en su lugar.
Si los servicios web ASMX se están actualizando y migrando, de forma paralela a los servicios WCF, evite la asignación de dos tipos al mismo nombre en el cliente. Esto produce una excepción en los serializadores si el mismo tipo se utiliza en WebMethodAttribute y ServiceContractAttribute:
Si se agrega primero el servicio WCF, que invoca al método en el servicio web ASMX produce una excepción en ConvertValue(Object, Type, String), porque la definición de estilo WCF de orden en el proxy tiene prioridad.
Si se agrega primero el servicio web ASMX, el método de invocación en el servicio WCF produce una excepción en DataContractJsonSerializer, porque la definición de estilo del servicio web de orden en el proxy tiene prioridad.
Hay diferencias significativas en el comportamiento entre DataContractJsonSerializer y el AJAX de ASP.NET JavaScriptSerializer. Por ejemplo, DataContractJsonSerializer representa un diccionario como una matriz de pares clave-valor, mientras que el JavaScriptSerializer de AJAX de ASP.NET representa un diccionario como objetos JSON reales. Por tanto lo siguiente es el diccionario representado en ASP.NET AJAX.
Dictionary<string, int> d = new Dictionary<string, int>();
d.Add("one", 1);
d.Add("two", 2);
Este diccionario se representa en objetos JSON como se muestra en la siguiente lista:
[{"Clave":"uno","Valor":1}, {"Clave":"dos","Valor":2}] por DataContractJsonSerializer
{"one":1,"two":2} por el JavaScriptSerializer de ASP.NET AJAX
DataContractJsonSerializer es más eficaz en el sentido de que puede controlar los diccionarios cuyo tipo de clave no es de cadena, mientras que JavaScriptSerializer no puede. Pero el último es más compatible con JSON.
Las diferencias significativas entre estos serializadores se resumen en la siguiente tabla.
Categoría de diferencias | DataContractJsonSerializer | JavaScriptSerializer de AJAX de ASP.NET |
---|---|---|
Deserializar el búfer vacío (nuevo byte [0]) en Object (o Uri o algunas otras clases). | SerializationException | null |
Serialización de Value | {} (or {"__type":"#System"}) | Null |
Serialización de los miembros privados de tipos [Serializable]. | serialized | not serialized |
Serialización de las propiedades públicas de los tipos ISerializable. | not serialized | serialized |
"Extensiones" de JSON | Conforme con la especificación de JSON, que requiere comillas en los nombres de miembro de objetos ({"a":"hola"}). | Admite los nombres de miembros de objeto sin comillas ({a:"hola"}). |
DateTimeHora universal coordinada (UTC) | No admite el formato "\/Date(123456789U)\/" or "\/Date\(\d+(U|(\+\-[\d{4}]))?\)\\/)". | Admite el formato "\/Date(123456789U)\/" and "\/Date\(\d+(U|(\+\-[\d{4}]))?\)\\/)" como valores DateTime. |
Representación de diccionarios | Una matriz de KeyValuePair<K,V> controla tipos clave que no son cadenas. | Como objetos JSON reales, pero solo controla los tipos clave que son cadenas. |
Caracteres con escape | Siempre con una barra diagonal de escape (/); nunca permite caracteres de JSON no válidos sin escape, como "\n". | Con una barra diagonal de escape (/) para los valores DateTime . |