2012-02-21 14 views
5

Ho un WebMethod che assomiglia a questo che viene utilizzato per popolare un jqGridCome faccio WebMethods serializzare 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; 
    } 

} 

"risultati" è una System.Dynamic.ExpandoObject con le proprietà Items, TotalPages, TotalRecords

jSON torno sulla dal webservice assomiglia a questo

{ 
"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 

Idealmente preferirei che ritorna senza tutte le attività chiave e il valore in quanto contribuisce ad appesantire fuori il json inutilmente e non gioca bene con jqGrid.

C'è un modo per modificare il modo in cui ASP.NET gestisce la serializzazione di ExpandoObject?

+0

Un amico consigliato questo approccio http://stackoverflow.com/questions/5156664/how-to-flatten-an-expandoobject-returned-via-jsonresult-in-asp -net-mvc ma non so come registrare JavaScriptConverter con JavaScriptSerializer che il noi usi di bmethod. –

+0

Accidenti, la risposta che cerco è qui http://msdn.microsoft.com/en-us/library/bb763183.aspx a circa metà strada –

+0

Buono a sapersi che hai imparato qualcosa di nuovo :) – Jull

risposta

4

Suona come hai già capito questo, ma ecco something I threw together a while back per fare proprio questo:

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

Poi, basta aggiungere alla sezione <converters> nel web.config, come mostrato in questo articolo di MSDN si è collegato al:

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

Sì, spero che questo aiuti qualcuno altro. Sebbene dovrebbe essere vergogna su MSDN. Grazie per la tua risposta rapida Dave, ama il lavoro, ama i tekpub vids –

+0

@SeanTomlins: Ack, c'è quello che ottengo per fidarmi ciecamente di MSDN! Grazie per la segnalazione. Ho modificato la mia risposta e inviato un messaggio a qualcuno alla MS per ottenere che l'errore fosse corretto. –

+0

Funziona alla grande tranne quando il valore è nullo. Aggiunto un controllo per esso e funziona bene. 'foreach (KeyValuePair elemento in 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