2011-01-20 12 views
6

Sto utilizzando l'HttpClient estremamente impressionante fornito nello Starter Kit REST WCF. Ho il seguente metodo che sta lavorando contro l'API HelloTxt:Richiesta POST generica mediante Microsoft.HttpClient e HttpContentExtensions

public UserValidateResponse Validate() 
{ 
    HttpClient client = new HttpClient(baseUrl); 

    HttpMultipartMimeForm form = new HttpMultipartMimeForm(); 
    form.Add("app_key", this.AppKey); 
    form.Add("user_key", this.UserKey); 
    HttpResponseMessage response = client.Post("user.validate", form.CreateHttpContent()); 

    return response.Content.ReadAsXmlSerializable<UserValidateResponse>(); 
} 

ho un bel metodo di GetRequest generico che assomiglia a questo:

public T GetRequest<T>(string query) 
{ 
    HttpClient client = new HttpClient(baseUrl); 
    client.DefaultHeaders.UserAgent.AddString(@"http://www.simply-watches.co.uk/"); 

    HttpResponseMessage response = client.Get(query); 
    response.EnsureStatusIsSuccessful(); 

    T data = default(T); 
    try 
    { 
     data = response.Content.ReadAsXmlSerializable<T>(); 
     return data; 
    } 
    catch (Exception ex) 
    { 
     Console.Write(String.Format("{0}: {1}", ex.Message, ex.InnerException.Message)); 
    } 

    return data; 
} 

Il vantaggio dei quali è che si può passare T come il tipo di risposta di cui al presente esempio a caso:

public List<User> GetUsers(int deptid) 
{ 
    string query = String.Format("department.getUsers?api_key={0}&dept_id={1}", this.APIKey, deptId); 

    return GetRequest<List<User>>(query); 
} 

ora voglio lo stesso metodo POST stile generico, piuttosto che GET e sono sicuro che posso utilizzare i HttpContentExtensions, ma non riesco a f Scopri come trasformare la richiesta in un HttpMultipartMimeForm. questo è quello che ho finora:

public T PostRequest<K, T>(string query, K request) 
{ 
    HttpClient client = new HttpClient(baseUrl); 
    // the following line doesn't work! Any suggestions? 
    HttpContent content = HttpContentExtensions.CreateDataContract<K>(request, Encoding.UTF8, "application/x-www-form-urlencoded", typeof(HttpMultipartMimeForm)); 

    HttpResponseMessage response = client.Post(query, content); 
    response.EnsureStatusIsSuccessful(); 

    T data = default(T); 
    try 
    { 
     data = response.Content.ReadAsXmlSerializable<T>(); 
     return data; 
    } 
    catch (Exception ex) 
    { 
     Console.Write(String.Format("{0}: {1}", ex.Message, ex.InnerException.Message)); 
    } 

    return data; 
} 

si sarebbe chiamato in questo modo:

UserValidateResponse response = PostRequest<UserValidateRequest, UserValidateResponse>("user.validate", new UserValidateRequest(this.AppKey, this.UserKey)); 

E 'a lavorare contro questa API: http://hellotxt.com/developers/documentation. Ogni suggerimento è estremamente gradito! Potrei definire una forma diversa per ogni POST, ma sarebbe bello farlo genericamente.

+0

ho la sensazione che l'unico modo per farlo è quello di utilizzare la riflessione e costruire un HttpMultipartMimeForm in base alle semplici proprietà di una classe, o di serializzare l'oggetto e quindi ottenere i primi bambini sotto il nodo XML root. – Junto

risposta

2

Ho risposto alla mia domanda su questo. Il codice può essere visto nel mio .NET wrapper for the HelloTxt API - HelloTxt.NET e, come per il mio commento sopra, utilizza la riflessione per elaborare le proprietà dell'oggetto di richiesta e inserisce uno HttpMultipartMimeForm() con i valori, controllando le anorie di dati Required nelle proprietà della classe.

Il codice in questione è:

/// <summary> 
/// Generic post request. 
/// </summary> 
/// <typeparam name="K">Request Type</typeparam> 
/// <typeparam name="T">Response Type</typeparam> 
/// <param name="query">e.g. user.validate</param> 
/// <param name="request">The Request</param> 
/// <returns></returns> 
public T PostRequest<K, T>(string query, K request) 
{ 
    using (var client = GetDefaultClient()) 
    { 
     // build form data post 
     HttpMultipartMimeForm form = CreateMimeForm<K>(request); 

     // call method 
     using (HttpResponseMessage response = client.Post(query, form.CreateHttpContent())) 
     { 
      response.EnsureStatusIsSuccessful(); 
      return response.Content.ReadAsXmlSerializable<T>(); 
     } 
    } 
} 

/// <summary> 
/// Builds a HttpMultipartMimeForm from a request object 
/// </summary> 
/// <typeparam name="T"></typeparam> 
/// <param name="request"></param> 
/// <returns></returns> 
public HttpMultipartMimeForm CreateMimeForm<T>(T request) 
{ 
    HttpMultipartMimeForm form = new HttpMultipartMimeForm(); 

    Type type = request.GetType(); 
    PropertyInfo[] properties = type.GetProperties(); 
    foreach (PropertyInfo property in properties) 
    { 
     foreach (Attribute attribute in property.GetCustomAttributes(true)) 
     { 
      RequiredAttribute requiredAttribute = attribute as RequiredAttribute; 
      if (requiredAttribute != null) 
      { 
       if (!requiredAttribute.IsValid(property.GetValue(request, null))) 
       { 
        //Console.WriteLine("{0} [type = {1}] [value = {2}]", property.Name, property.PropertyType, property.GetValue(property, null)); 
        throw new ValidationException(String.Format("{0} [type = {1}] requires a valid value", property.Name, property.PropertyType)); 
       } 
      } 
     } 

     if (property.PropertyType == typeof(FileInfo)) 
     { 
      FileInfo fi = (FileInfo)property.GetValue(request, null); 
      HttpFormFile file = new HttpFormFile(); 
      file.Content = HttpContent.Create(fi, "application/octet-stream"); 
      file.FileName = fi.Name; 
      file.Name = "image"; 

      form.Files.Add(file); 
     } 
     else 
     { 
      form.Add(property.Name, String.Format("{0}", property.GetValue(request, null))); 
     } 
    } 

    return form; 
} 
Problemi correlati