2011-01-20 7 views
6

私はWCF RESTスターターキットで提供されている非常に素晴らしいHttpClientを使用しています。 Microsoft.HttpClientとHttpContentExtensionsを使用した一般的なPOSTリクエスト

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

が、私はこのようになります素敵なジェネリックのGetRequestメソッドを持っている:私はHelloTxtのAPI不利に働いている次のような方法があります

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; 
} 
の利点は、あなたがTにそれを渡すことができるということです

このランダムな例のように応答タイプとして:

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

私は今、同じ一般的なスタイルのPOSTメソッドにしたい、というよりもGETと私はHttpContentExtensionsを使用することができると確信していますが、私はFすることはできませんリクエストをHttpMultipartMimeFormに変換する方法を説明してください。これは私がこれまで持っているものです。

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

それはこのように呼ばれます:http://hellotxt.com/developers/documentation

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

これは、このAPIに対して動作することです。どんな提案も大歓迎です! POSTごとに異なるフォームを定義することもできますが、これを一般的に行うとよいでしょう。

+0

私はこれを行うための唯一の方法は、リフレクションを使用して、クラスの単純なプロパティに基づいてHttpMultipartMimeFormを構築するか、オブジェクトをシリアル化してから取得することです感じています最初の子はルートXMLノードの下にあります。 – Junto

答えて

2

私はこれに関する自分の質問に答えました。コードは私の.NET wrapper for the HelloTxt API - HelloTxt.NETで見ることができ、上記の私のコメントによると、要求オブジェクトのプロパティを調べるためにリフレクションを使用し、に値を設定しながら、クラスプロパティのRequiredデータ注釈をチェックします。

問題のコードは次のとおりです。

/// <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; 
} 
関連する問題