2016-11-23 6 views
5

Ich habe versucht, eine kleine Demo einzurichten, in der ein Artikel mehrere Kommentare hat. Die Artikeldetailansicht sollte die Kommentare in einer Teilansicht darstellen. Die Teilansicht selbst enthält eine weitere Teilansicht zum Hinzufügen eines neuen Kommentars.Warum ruft das PartialView sich selbst auf?

Wenn ich versuche, einen weiteren Kommentar hinzuzufügen, erhalte ich eine InsufficientExecutionStackException, weil die Aktion in der Steuerung sich selbst anruft. Warum passiert das?

(Wenn jemand hat das Kursmaterial zur Hand Ein ähnliches Beispiel bei Modul 9 in dem 70-486 Kurs von Msft sein sollte, das ist, was ich zu bauen versucht..)

Edit: Der vollständige Code ist auf github

Edit2: Die Probe auf Github wurde behoben. Wie Stephen Mücke hervorhob, verursachte die Tatsache, dass sowohl die GET als auch die POST Methode die gleichen Namen hatten, den Zirkelverweis. Bevor irgendjemand mehr darauf hinweist, dass DI- und View-Modelle fehlen und dass das Rendern aller Kommentare suboptimal ist: Ja, mir ist klar, und nein, diese Dinge waren nichts, was ich erreichen wollte. Das war nur eine kurze n schmutzige Demo.

Controller:

[ChildActionOnly] 
public PartialViewResult _GetCommentsForArticle(int articleId) 
{ 
    ViewBag.ArticleId = articleId; 
    var comments = db.Comments.Where(x => x.Article.ArticleId == articleId).ToList(); 
    return PartialView("_GetCommentsForArticle", comments); 
} 


public PartialViewResult _CreateCommentForArticle(int articleId) 
{ 
    ViewBag.ArticleId = articleId; 
    return PartialView("_CreateCommentForArticle"); 
} 

[HttpPost] 
public PartialViewResult _CreateCommentForArticle(Comment comment, int articleId) 
{ 
    ViewBag.ArticleId = articleId; 
    comment.Created = DateTime.Now; 
    if (ModelState.IsValid) 
    { 
     db.Comments.Add(comment); 
     db.SaveChanges(); 
    } 
    var comments = db.Comments.Where(x => x.Article.ArticleId == articleId).ToList(); 
    return PartialView("_GetCommentsForArticle", comments); 
} 

entsprechende Zeile in der Details.cshtml für Artikel:

@Html.Action("_GetCommentsForArticle", "Comments", new { articleId = Model.ArticleId}) 

_GetCommentsForArticle:

@model IEnumerable<Mod9_Ajax.Models.Comment> 
<div id="all-comments"> 
    <table class="table"> 
     <tr> 
      <th> 
       @Html.DisplayNameFor(model => model.Text) 
      </th> 
     </tr> 

     @foreach (var item in Model) 
     { 
      @* ... *@ 
     } 
    </table> 
</div> 
@Html.Action("_CreateCommentForArticle", "Comments", new { articleId = ViewBag.ArticleId }) 

_CreateCommentForArticle:

@model Mod9_Ajax.Models.Comment 
@using (Ajax.BeginForm("_CreateCommentForArticle", "Comments", new AjaxOptions 
{ 
    HttpMethod = "POST", 
    InsertionMode = InsertionMode.Replace, 
    UpdateTargetId = "all-comments" 
})) 
{ 
    @* ... *@ 

     <div class="form-group"> 
      <div class="col-md-offset-2 col-md-10"> 
       <input type="submit" value="Create" class="btn btn-default" /> 
      </div> 
     </div> 
    </div> 
} 
+0

Als beiseite zu passen, wenn das Trainingsmaterial wird Ihnen anweist, Verwenden Sie eine Entity Model-Klasse als ViewModel oder DTO, dann sollte ich Ihnen sagen, dass es eine schlechte Übung ist - verwenden Sie immer einen dedizierten ViewModel/DTO-Typ, anstatt Entity Model-Typen erneut zu verwenden. – Dai

+1

Ich replizierte nur Ihre Ansichten in einem neuen leeren Projekt mit einer einfachen 'CommentsController :: Details' Aktion und ich kann dieses Problem nicht reproduzieren. Kannst du dein gesamtes Projekt irgendwo in einem Zip/Archiv posten? – Dai

+0

Warum gibt die POST-Methode alle Kommentare zurück, wenn Sie sie bereits in der Ansicht haben (im Gegensatz zum Hinzufügen des neuen Kommentars zur Ansicht) –

Antwort

1

Um zu erklären, was passiert, haben Sie ein Formular, das Ihnen _CreateCommentForArticle() Methode postet, die dann Ihre _GetCommentsForArticle.cshtml teilweise darstellt, die wiederum @Html.Action("_CreateCommentForArticle", ...) enthält.

In der Anfangs GET-Methode für Details() wird die Ansicht korrekt wiedergegeben werden, aber wenn Sie das Formular abschicken, ist die aktuelle Anforderung für die _GetCommentsForArticle Seite eine [HttpPost] Methode, so wird @Html.Action() für eine [HttpPost] Methode sucht (nicht die [HttpGet] Methode). Das [HttpPost] wiederum macht die _GetCommentsForArticle.cshtml teilweise und ruft wieder die _CreateCommentForArticle() POST-Methode, die die _GetCommentsForArticle.cshtml partiellen und so weiter rendert, bis Sie nicht mehr genügend Arbeitsspeicher und die Ausnahme ausgelöst wird.

Sie können dieses Problem lösen, indem Sie den Namen der POST-Methode zu ändern, zum Beispiel

[HttpPost] 
public PartialViewResult Create(Comment comment, int articleId) 

und die Form ändern

@using (Ajax.BeginForm("Create", "Comments", new AjaxOptions { ... 
+0

Ich saß gerade im Labor und kam zu demselben Schluss. Dies ist genau das, was fehlgeschlagen ist. Nachdem ich die Aktion mit '[HttpPost, ActionName (" _ PostCreate ")]' geschmückt und die 'Ajax.BeginForm' verändert hatte, begann sie zu arbeiten. – Marco

+0

Es gibt viel unnötigen Code in Ihrer App und Sie beeinträchtigen die Leistung, indem Sie mindestens 2 unnötige Datenbankaufrufe durchführen. Wenn ich eine Chance bekomme, werde ich die Antwort mit einigen weiteren Kommentaren aktualisieren. –

+0

Mir sind alle (gut, die meisten) Mängel bekannt. Ich kratzte mich am Kreis herum. Der Code war die Standard-MVC-Vorlage von Visual Studio und fügte dann einfach die Modelle und die DAL hinzu, um meinen Standpunkt zu demonstrieren. (Und das ist wirklich, wie der Kurs 70-486 Ajax demonstriert. Nur doppelt überprüft) – Marco

Verwandte Themen