2012-02-21 11 views
5

Tengo un WebMethod que tiene este aspecto que se utiliza para rellenar un jqGrid¿Cómo hago webMethods serializar ExpandoObject

[System.Web.Script.Services.ScriptService] 
public class MyWebService: System.Web.Services.WebService 
{ 
    [WebMethod] 
    [Authorize(Roles = "Admin")] 
    public object GetPeople(bool _search, double nd, int rows, int page, string sidx, string sord) 
    { 
     var tbl = new DynamicModel("ConnStr", tableName: "Person", primaryKeyField: "ID"); 
     var results = tbl.Paged(orderBy: sidx + " " + sord, currentPage: page, pageSize: rows); 
     return results; 
    } 

} 

"resultados" es un System.Dynamic.ExpandoObject con las propiedades de elementos, TotalPages, TotalRecords

el JSON que regrese a la del servicio web se parece a esto

{ 
"d": [{ 
    "Key": "TotalRecords", 
    "Value": 1 
}, { 
    "Key": "TotalPages", 
    "Value": 1 
}, { 
    "Key": "Items", 
    "Value": [ 
     [{ 
      "Key": "Row", 
      "Value": 1 
     }, { 
      "Key": "ID", 
      "Value": 1 
     }, { 
      "Key": "Name", 
      "Value": "Test Template" 
     }] 
    ] 
}] 
} 
} // Don't know why firebug put this extra bracket 

lo ideal sería que preferiría que se trata de volver sin todo el negocio clave y valor, ya que se hincha fuera del json innecesariamente y no juega muy bien con jqGrid.

¿Hay alguna manera de cambiar la forma en que ASP.NET maneja la serialización de ExpandoObject?

+0

Un amigo me recomendó este enfoque http://stackoverflow.com/questions/5156664/how-to-flatten-an-expandoobject-returned-via-jsonresult-in-asp -net-mvc pero no sé cómo registrar el JavaScriptConverter con el JavaScriptSerializer que el bmethod usa. –

+0

Maldita sea, la respuesta que busco está aquí http://msdn.microsoft.com/en-us/library/bb763183.aspx a mitad de camino –

+0

Es bueno saber que aprendiste algo nuevo :) – Jull

Respuesta

4

Suena como que ya ha dado cuenta de esto, pero aquí está something I threw together a while back de hacer precisamente eso:

public class ExpandoObjectConverter : JavaScriptConverter { 
    public override IEnumerable<Type> SupportedTypes { 
    get { return new ReadOnlyCollection<Type>(new List<Type>(new Type[] { typeof(ExpandoObject) })); } 
    } 

    public override IDictionary<string, object> Serialize(object obj, JavaScriptSerializer serializer) { 
    ExpandoObject expando = (ExpandoObject)obj; 

    if (expando != null) { 
     // Create the representation. 
     Dictionary<string, object> result = new Dictionary<string, object>(); 

     foreach (KeyValuePair<string, object> item in expando) { 
     if (item.Value.GetType() == typeof(DateTime)) 
      result.Add(item.Key, ((DateTime)item.Value).ToShortDateString()); 
     else 
      result.Add(item.Key, item.Value.ToString()); 
     } 

     return result; 
    } 
    return new Dictionary<string, object>(); 
    } 

    public override object Deserialize(IDictionary<string, object> dictionary, Type type, JavaScriptSerializer serializer) { 
    return null; 
    } 
} 

A continuación, sólo tiene que añadirlo a la sección <converters> en su web.config, como se muestra en el artículo de MSDN se ha vinculado a:

<configuration> 
    <system.web.extensions> 
    <scripting> 
     <webServices> 
     <jsonSerialization> 
      <converters> 
      <add name="ExpandoObjectConverter" type="ExpandoObjectConverter"/> 
      </converters> 
     </jsonSerialization> 
     </webServices> 
    </scripting> 
    </system.web.extensions> 
</configuration> 
+0

Sí, afortunadamente esto ayuda a alguien más. Aunque debería ser vergüenza en MSDN. Gracias por su respuesta rápida Dave, me encanta el trabajo, me encantan los videos de tekpub –

+0

@SeanTomlins: ¡Ack, hay lo que recibo por confiar ciegamente en MSDN! Gracias por señalar eso. Edité mi respuesta y llamé a alguien de MS para que solucionara ese error. –

+0

Funciona muy bien, excepto cuando el valor es nulo. Se agregó un cheque y funciona bien. 'foreach (KeyValuePair elemento en expando) { if (item.Value == null) result.Add (item.Key, string.Empty); else if (item.Value.GetType() == typeof (DateTime)) result.Add (item.Key, ((DateTime) item.Value) .ToShortDateString()); else result.Add (item.Key, item.Value.ToString()); } ' – sarme