2013-03-16 49 views
2

我正在開發一個簡單的Web應用程序,我需要將所有類型的實現和特定類型的接口綁定在一起。我的接口有這樣使用Web API和RavenDB進行繼承的自定義模型聯編程序

public interface IContent { 
    string Id { get;set; } 
} 
使用這個接口應該是這樣的

public class Article : IContent { 
    public string Id { get;set; } 
    public string Heading { get;set; } 
} 

是乾淨這裏的文章類只是實現IContent這麼爲此許多不同類別的一個

一類常見單一屬性我需要一種通用的方式來存儲和更新這些類型。

所以在我的控制器我有put方法這樣

public void Put(string id, [System.Web.Http.ModelBinding.ModelBinder(typeof(ContentModelBinder))] IContent value) 
{ 
    // Store the updated object in ravendb 
} 

和ContentBinder

public class ContentModelBinder : System.Web.Http.ModelBinding.IModelBinder { 
    public bool BindModel(HttpActionContext actionContext, ModelBindingContext bindingContext) { 

     actionContext.ControllerContext.Request.Content.ReadAsAsync<Article>().ContinueWith(task => 
     { 
      Article model = task.Result; 
      bindingContext.Model = model; 
     }); 

     return true; 
    } 

} 

上面的代碼不起作用,因爲它似乎並沒有得到鐓性能的保持即使如果我使用默認模型聯編程序它正確地綁定標題。

因此,在BindModel方法中,我想我需要從ravendb基於Id加載正確的對象,然後使用某種默認模型綁定器更新複雜對象,或者等等?這是我需要幫助的地方。

+0

@ matt-johnson其實我不知道如何更新模型,但我已經用一些代碼更新了我的問題,但這只是爲了試驗和錯誤。 – Marcus 2013-03-16 16:17:33

+0

@MattJohnson也許有可能使用HttpContent.ReadAsAsync 或其他的反序列化json到一個特定的類型? – Marcus 2013-03-16 16:58:37

+0

@ matt-johnson我用ReadAsAsync更新了我的代碼,但我無法弄清楚爲什麼這樣不起作用? – Marcus 2013-03-16 19:06:05

回答

0

我使用@ kiran-challa解決方案並在Json媒體類型格式化程序的SerializerSettings上添加了TypeNameHandling。

2

Marcus,以下是對Json和Xml格式化程序均可正常工作的示例。

using Newtonsoft.Json; 
using System; 
using System.Collections.Generic; 
using System.Net; 
using System.Net.Http; 
using System.Net.Http.Formatting; 
using System.Net.Http.Headers; 
using System.Runtime.Serialization; 
using System.Web.Http; 
using System.Web.Http.SelfHost; 

namespace Service 
{ 
    class Service 
    { 
     private static HttpSelfHostServer server = null; 
     private static string baseAddress = string.Format("http://{0}:9095/", Environment.MachineName); 

     static void Main(string[] args) 
     { 
      HttpSelfHostConfiguration config = new HttpSelfHostConfiguration(baseAddress); 
      config.Routes.MapHttpRoute("Default", "api/{controller}/{id}", new { id = RouteParameter.Optional }); 
      config.IncludeErrorDetailPolicy = IncludeErrorDetailPolicy.Always; 
      config.Formatters.JsonFormatter.SerializerSettings.TypeNameHandling = TypeNameHandling.Objects; 

      try 
      { 
       server = new HttpSelfHostServer(config); 
       server.OpenAsync().Wait(); 

       Console.WriteLine("Service listenting at: {0} ...", baseAddress); 

       TestWithHttpClient("application/xml"); 

       TestWithHttpClient("application/json"); 

       Console.ReadLine(); 
      } 
      catch (Exception ex) 
      { 
       Console.WriteLine("Exception Details:\n{0}", ex.ToString()); 
      } 
      finally 
      { 
       if (server != null) 
       { 
        server.CloseAsync().Wait(); 
       } 
      } 
     } 

     private static void TestWithHttpClient(string mediaType) 
     { 
      HttpClient client = new HttpClient(); 

      MediaTypeFormatter formatter = null; 

      // NOTE: following any settings on the following formatters should match 
      // to the settings that the service's formatters have. 
      if (mediaType == "application/xml") 
      { 
       formatter = new XmlMediaTypeFormatter(); 
      } 
      else if (mediaType == "application/json") 
      { 
       JsonMediaTypeFormatter jsonFormatter = new JsonMediaTypeFormatter(); 
       jsonFormatter.SerializerSettings.TypeNameHandling = TypeNameHandling.Objects; 

       formatter = jsonFormatter; 
      } 

      HttpRequestMessage request = new HttpRequestMessage(); 
      request.RequestUri = new Uri(baseAddress + "api/students"); 
      request.Method = HttpMethod.Get; 
      request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue(mediaType)); 
      HttpResponseMessage response = client.SendAsync(request).Result; 
      Student std = response.Content.ReadAsAsync<Student>().Result; 

      Console.WriteLine("GET data in '{0}' format", mediaType); 
      if (StudentsController.CONSTANT_STUDENT.Equals(std)) 
      { 
       Console.WriteLine("both are equal"); 
      } 

      client = new HttpClient(); 
      request = new HttpRequestMessage(); 
      request.RequestUri = new Uri(baseAddress + "api/students"); 
      request.Method = HttpMethod.Post; 
      request.Content = new ObjectContent<Person>(StudentsController.CONSTANT_STUDENT, formatter); 
      request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue(mediaType)); 
      Student std1 = client.SendAsync(request).Result.Content.ReadAsAsync<Student>().Result; 

      Console.WriteLine("POST and receive data in '{0}' format", mediaType); 
      if (StudentsController.CONSTANT_STUDENT.Equals(std1)) 
      { 
       Console.WriteLine("both are equal"); 
      } 
     } 
    } 

    public class StudentsController : ApiController 
    { 
     public static readonly Student CONSTANT_STUDENT = new Student() { Id = 1, Name = "John", EnrolledCourses = new List<string>() { "maths", "physics" } }; 

     public Person Get() 
     { 
      return CONSTANT_STUDENT; 
     } 

     // NOTE: specifying FromBody here is not required. By default complextypes are bound 
     // by formatters which read the body 
     public Person Post([FromBody] Person person) 
     { 
      if (!ModelState.IsValid) 
      { 
       throw new HttpResponseException(Request.CreateErrorResponse(HttpStatusCode.BadRequest, this.ModelState)); 
      } 

      return person; 
     } 
    } 

    [DataContract] 
    [KnownType(typeof(Student))] 
    public abstract class Person : IEquatable<Person> 
    { 
     [DataMember] 
     public int Id { get; set; } 

     [DataMember] 
     public string Name { get; set; } 

     // this is ignored 
     public DateTime DateOfBirth { get; set; } 

     public bool Equals(Person other) 
     { 
      if (other == null) 
       return false; 

      if (ReferenceEquals(this, other)) 
       return true; 

      if (this.Id != other.Id) 
       return false; 

      if (this.Name != other.Name) 
       return false; 

      return true; 
     } 
    } 

    [DataContract] 
    public class Student : Person, IEquatable<Student> 
    { 
     [DataMember] 
     public List<string> EnrolledCourses { get; set; } 

     public bool Equals(Student other) 
     { 
      if (!base.Equals(other)) 
      { 
       return false; 
      } 

      if (this.EnrolledCourses == null && other.EnrolledCourses == null) 
      { 
       return true; 
      } 

      if ((this.EnrolledCourses == null && other.EnrolledCourses != null) || 
       (this.EnrolledCourses != null && other.EnrolledCourses == null)) 
       return false; 

      if (this.EnrolledCourses.Count != other.EnrolledCourses.Count) 
       return false; 

      for (int i = 0; i < this.EnrolledCourses.Count; i++) 
      { 
       if (this.EnrolledCourses[i] != other.EnrolledCourses[i]) 
        return false; 
      } 

      return true; 
     } 
    } 
} 
相關問題