2016-08-04 32 views
5

Sagen wir, ich habe eine API, die einfache Nachrichten an Benutzer sendet. Um es zu schicken würde ich so etwas wie verwenden:Sollte ich zwei verschiedene Modellklassen zum Lesen und Aktualisieren von Objekten in der Web-API haben?

POST { 
     Content: "Message here", 
     To: "[email protected]" 
} api/messages 

Jetzt möchte ich alle gesendeten Nachrichten lesen, aber mit Benutzer, der es senden (ich hatte Identität in Cookie) und Sendezeit (automatisch vergeben). Auch hier scheint es einfach zu sein:

GET api/messages 

und ich bekommen:

[{ 
    Content: "Message here", 
    To: "[email protected]", 
    From: "user1", 
    Time: "0001-01-01T00:00:00" 
}] 

Von API-Controller Seite werde ich zwei Methoden:

public class MessagesController : ApiController 
{ 
    [HttpPost, Route("Messages")] 
    public HttpResponseMessage Post([FromBody] Message message) 
    { 
     messageRepository.Create(message); 
     return Request.CreateResponse(HttpStatusCode.Created, "Message was send."); 
    } 

    [HttpGet, Route("Messages")] 
    public HttpResponseMessage Get() 
    { 
     var response = new HttpResponseMessage(HttpStatusCode.OK) 
     { 
      Content = new StringContent(JsonConvert.SerializeObject(messageRepository.GetMessages())) 
     }; 
     response.Content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/json"); 
     return response; 
    } 
} 

Mein Problem ist, dass das Objekt, was Senden ist anders als Objekt, was ich bekomme. Also ich denke, ich kann nicht dieselbe Message-Klasse verwenden. Warum sollte ich dann tun:

  • Sollte ich zwei verschiedene Klassen hier haben, um es richtig zu machen? (Ich werde mehr Code haben und ich weiß nicht, ob es aus Sicht der REST korrekt ist)
  • Sollte ich eine Klasse verwenden, aber die Eigenschaften Von und Zeit ignorieren, wenn der Benutzer sie mir sendet?
  • Sollte ich meinem Benutzer sagen, dass er mir "From" und "Time" sendet, aber hier null sendet?
+2

Denken Sie an die Objekte, die über die Leitung als DTOs (Data Transfer Objects) gesendet werden. Es wird normalerweise empfohlen, dass Sie nur das senden, was über die Leitung notwendig ist. Dein JavaScript-Client sollte also nur das aufbauen, was die API erwartet. Wenn von und Zeit etwas ist, das der Client nicht bereitstellen muss, sollte es das nicht tun. Aus Sicherheitsgründen möchten Sie nicht mehr Informationen verlieren als für den Client erforderlich. – Nkosi

Antwort

4

Denken Sie an die Objekte, die als DTOs (Data Transfer Objects) über die Leitung gesendet werden. Es wird normalerweise empfohlen, dass Sie nur das senden, was über die Leitung notwendig ist.

Also sollte Ihr Client nur konstruieren, was die API erwartet. Wenn From und Time Daten sind, die der Client nicht bereitstellen muss, sollte dies nicht der Fall sein.

public class PostMessageDto { 
    public string Content { get; set; } 
    public string To {get; set; } 
} 

Aus Sicherheitsgründen möchten Sie nicht mehr Informationen als für den Client erforderlich. Wenn Ihre Entitäten mehr Informationen offenlegen, als Sie anzeigen möchten, sollten Sie ein Modell erstellen, um nur die Details zu übergeben, die an den Client gesendet werden sollen.

public class MessagesController : ApiController { 
    //POST api/messages 
    [HttpPost, Route("Messages")] 
    public HttpResponseMessage Post([FromBody] PostMessageDto message) { 
     var entity = new Message { 
      Content = message.Content, 
      To = message.To 
     }; 
     messageRepository.Create(entity); 
     return Request.CreateResponse(HttpStatusCode.Created, "Message was send."); 
    } 

    //GET api/messages  
    [HttpGet, Route("Messages")] 
    public HttpResponseMessage Get() { 
     var entities = messageRepository.GetMessages(); 

     //..you can put code here that creates the data you want returned. 
     var responseData= entities.Select(x => new { 
      Content = x.Content, 
      To = x.To, 
      From = x.From, 
      Time = x.Time 
     }); 

     var response = Request.CreateResponse(HttpStatusCode.OK, responseData); 
     response.Content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/json"); 
     return response; 
    } 
}