2012-07-31 6 views
10

Ich habe eine ziemlich gut gestaltete Architektur, in der Controller zu Diensten gehen, die auf Repositories zugreifen, die mit der Datenbank kommunizieren.Wie halten Sie Controller in ASP.NET MVC klein?

Als solche Logik in Controller auf einem Minimum gehalten, aber ich habe noch sehr subtile Stücke von Code, der wie einige Aufgaben ausführen

  • bestätigen das Modell
  • die Aktionsmethode Argumente ordnen
  • rufen Sie einen Service mit diesen Argumenten auf, validieren Sie vielleicht das Ergebnis und geben Sie die Ansicht zurück, wenn das Modell jetzt
  • ist, schließlich ein Modell aus dem Ergebnis des Dienstes erzeugt und das zurückgibt.

einige längere Fälle unterscheiden sich je nach Status, der vom Dienst zurückgegeben wird.

hier ein paar Beispiele:

[HttpPost] 
[AjaxOnly] 
[Authorize] 
public JsonResult Preview(string input) 
{ 
    LinkResult parsed = linkService.ParseUserInput(input); 
    if (parsed.Result == LinkParseResult.Used) 
    { 
     long? postId = parsed.Link.PostId; 
     if (postId.HasValue) 
     { 
      Post post = postService.GetById(postId.Value, false); 
      return Json(new 
      { 
       faulted = "used", 
       link = DetailsRoute(post), 
       id = postId 
      }); 
     } 
     else 
     { 
      return Json(new { faulted = "invalid" }); 
     } 
    } 
    else if (parsed.Result == LinkParseResult.Invalid) 
    { 
     return Json(new { faulted = "invalid" }); 
    } 
    else 
    { 
     Link link = parsed.Link; 
     if (link.Description != null && link.Description.Length > 200) 
     { 
      link.Description = link.Description.Substring(0, 200); 
     } 
     return AjaxView(link); 
    } 
} 

und (Post von Domain kommt, PostModel ist der Ansicht Modell)

private PostModel PostModelConverter(Post post) 
{ 
    Link link = post.Link; 
    if (link == null) 
    { 
     throw new ArgumentException("post.Link can't be null"); 
    } 
    if (link.Type == LinkType.Html) 
    { 
     return new PostedLinkModel 
     { 
      Description = link.Description, 
      PictureUrl = link.Picture, 
      PostId = post.Id, 
      PostSlug = postService.GetTitleSlug(post), 
      Timestamp = post.Created, 
      Title = link.Title, 
      UserMessage = post.UserMessage, 
      UserDisplayName = post.User.DisplayName 
     }; 
    } 
    else if (link.Type == LinkType.Image) 
    { 
     return new PostedImageModel 
     { 
      PictureUrl = link.Picture, 
      PostId = post.Id, 
      PostSlug = postService.GetTitleSlug(post), 
      Timestamp = post.Created, 
      UserMessage = post.UserMessage, 
      UserDisplayName = post.User.DisplayName 
     }; 
    } 
    return null; 
} 

stellt sich die Frage nach, ob Ansicht Modelle wirklich in der sein sollte, Webprojekt in der Regel, oder sie könnten tatsächlich Teil der Domäne oder eines anderen Projekts sein.

Ich bin mir nicht sicher, kann ich viel über die Vorschau Aktion, außer vielleicht ein PreviewModel, das den Link erhält, und schneidet die Beschreibung, aber das würde wie zwei Zeilen speichern.

Der Modellkonverter sollte wahrscheinlich woanders sein, aber ich weiß nicht, wo das sein sollte. Ein weiterer Punkt, der mir in den Sinn kommt, ist, ob ich diesen Controller unter Verwendung des Schlüsselwortes partial spalten sollte (ist es eine schlechte Übung, dies für etwas anderes als automatisch generierte Klassen zu verwenden?), Oder Routen hinzuzufügen, die unterschiedliche Controller verwenden Welche Aktion wird angefordert oder welche http-Methode wird verwendet, wie geht das normalerweise?

+0

Nur eine persönliche Vorliebe, aber Sie können Switch-Anweisungen anstelle von wenn .. sonst verwenden, wenn ... usw. –

Antwort

4

Dies wurde mehrmals gefragt:
Business logic in the controller
Where should I put my controller business logic in MVC3
Keep Controllers Thin

sowie über an anderer Stelle geschrieben:
ASP MVC Best Practices - Skinny Controllers
Keep Controllers Thin

Die Gemeinschaft scheint sich einig zu sein, dass diese Art von Logik außerhalb der Controller liegt. Im Allgemeinen im Modell (oder ViewModel), aber irgendwo in der Business-Schicht.

Als letzte Anmerkung wird die Verwendung partials für nicht automatisch generierten Code nicht abgeraten. Wenn es Sinn macht, Dinge zu spalten, tue es.Denken Sie nur darüber nach, was Ihre Gründe dafür sind. Das wird von Fall zu Fall so sein.

2
private PostModel PostModelConverter(Post post) 
{ 
    Link link = post.Link; 
    if (link == null) 
    { 
     throw new ArgumentException("post.Link can't be null"); 
    } 
    if (link.Type == LinkType.Html) 
    { 
     var model = AutoMapper.Map<PostedLinkModel>(post); 
     model.PostSlug = postService.GetTitleSlug(post); 
     return model; 
    } 
    else if (link.Type == LinkType.Image) 
    { 
     var model = AutoMapper.Map<PostedImageModel>(post); 
     model.PostSlug = postService.GetTitleSlug(post); 
     return model; 
    } 
    return null; 
} 

http://www.viddler.com/v/b568679c

0

-Controller werden keine Domain-Logik enthalten

-Controller sollte nur dann verantwortlich sein:

Validieren Eingang

Modell Aufruf der Ansicht,

Return um die Ansicht zu erstellen oder Umleiten zu einer anderen Aktion

Wenn Sie etwas anderes tun, tun Sie es an einem falschen Ort, es ist eher die Modell Verantwortung, die Sie in Controller tun.

Wenn Sie dieser Regel folgen, wird Ihre Aktionsmethode nicht mehr als 20 - 25 Zeilen Code enthalten. Ian Cooper hat einen ausgezeichneten Beitrag Skinny Controller Fat Model, lesen Sie es.