2016-09-30 1 views
0

Das Viewdata Element, das den Schlüssel ‚SelectedRating‘ hat, ist vom Typ ‚System.Int32‘, sondern muss vom Typ "IEnumerable" sein.MVC - Dropdownlist/PartialView Ausgabe - „Viewdata hat den Schlüssel int .. ..must IUnumerable sein ...“

Dies ist der Fehler, den ich erhalte, wenn ich versuche, eine DropDownList über eine Teilansicht hinzuzufügen. Ich habe versucht, zu folgen this solution, aber ich habe es irgendwie aufgrund meiner geringen Erfahrung in der Codierung versäumt, dies zu tun. Diese

ist, wie mein Code Look für den Moment:

[HttpGet] 
    public ActionResult Rating() 
    { 
     RateReviewVM model = new RateReviewVM() 
     { 
      ReviewId = id, 
      RatingList = new SelectList(Enumerable.Range(1, 10)) 
     }; 
     return View(model); 
    } 

    [HttpPost] 
    public ActionResult Rating(RateReviewVM model) { 

     if (!ModelState.IsValid) 
     {     
      model.RatingList = new SelectList(Enumerable.Range(1, 10)); 
      return View(model); 
     } 

     //... 

Ansicht für _RatingPartial

@model xxxx.ViewModel.RateReviewVM 

<h6>Rate the review</h6> 

using (Html.BeginForm()) { 

<div class="form-group"> 


    @Html.LabelFor(m => m.SelectedRating) 
    @Html.DropDownListFor(m => m.SelectedRating, Model.RatingList, "-Please select-", new { @class = "form-control" }) 
    @Html.ValidationMessageFor(m => m.SelectedRating) 

</div> 

<button type="submit" class="btn btn-default submit">Rate</button> 
    } 
} 

Dies ist, wie ich versuche,

@{ 
    var newRating = new xxxx.ViewModel.RateReviewVM { ReviewId = Model.Id }; 

    Html.RenderPartial("_RatingPartial", newRating); 

} 
_RatingPartial Ansicht anzuzeigen

Modell

public class RateReviewVM { 

      public System.Guid Id { get; set; } 

      public System.Guid UserId { get; set; } 

      public System.Guid ReviewId { get; set; } 

      public bool HasLiked { get; set; } 

      public Nullable<int> Rating { get; set; } 

      public int SelectedRating { get; set; } 

      public IEnumerable<SelectListItem> RatingList { get; set; } 
    } 

EDIT: ---

Details anzeigen (Haupt)

@model xxxx.Review 

    @{ 
     ViewBag.Title = "Details"; 
    } 

    @*@{ 
     //var newRating = new xxxx.ViewModel.RateReviewVM { ReviewId = Model.Id }; 

     @Html.RenderPartial("_RatingPartial", newRating) 

    }*@ 

    <h2>Details</h2> 

    <div> 

     <h4>Review</h4> 
     <hr/> 
     <dl class="dl-horizontal"> 
      <dt> 
       @Html.DisplayNameFor(model => model.Title) 
      </dt> 

      <dd> 
       @Html.DisplayFor(model => model.Title) 
      </dd> 

      <dt> 
       @Html.DisplayNameFor(model => model.Description) 
      </dt> 

      <dd> 
       @Html.DisplayFor(model => model.Description) 
      </dd> 
      @* and so on.. *@ 

     </dl> 
    </div> 
    <p> 
     @Html.ActionLink("Back to List", "Index") 
    </p> 

Controller für Einzelheiten

  public ActionResult Details(Guid? id) { 

      Review review = db.Reviews.Find(id); 

      return View(review); 
     } 

Modell Bewertung für Einzelheiten

 public System.Guid Id { get; set; } 

     public System.Guid CreatorUserId { get; set; } 

     [Required] 
     public string Title { get; set; } 

     [Required] 
     public string Description { get; set; } 

     public System.DateTime CreatedDate { get; set; } 

     //etc - some irrelevant property   

     public virtual ICollection<RateReview> Users { get; set; } 
+0

Ihre 'RenderPartial()' initialisiert gerade eine neue Instanz von 'RateReviewVM' und Sie haben die' RatingList' Eigenschaft dieser Instanz nicht gefüllt (ihre 'null', daher die Ausnahme). Warum benutzt du 'RenderPartial()'? Und was ist das Modell in der Hauptansicht? –

+0

@StephenMuecke Ich dachte, das war das richtige um ein Partial anzuzeigen. Was sollte ich stattdessen verwenden? – skylake

+0

Ihre GET-Methode schlägt vor, dass das Modell in der Hauptansicht bereits 'RateReviewVM' ist. Was ist der Sinn von' RenderPartial() '? Verschieben Sie einfach den Code in der '_RatingPartial.cshtml' Datei in die' Rating.cshtml' Datei und löschen Sie 'RenderPartial()' –

Antwort

1

Der Grund für den Fehler ist, dass der Wert von RatingList ist null (siehe The ViewData item that has the key 'XXX' is of type 'System.Int32' but must be of type 'IEnumerable' für ein detaillierten Erläuterung).

In Ihrem Fall Ihre die RenderPartial() Methode unter Verwendung eines Modells zur Ansicht übergeben, und Sie setzen den Wert der Immobilie RatingList (RenderPartial nicht Ihre public ActionResult Rating() Methode nicht nennen.

Sie den Fehler beheben könnte durch mit

@{ 
    var newRating = new xxxx.ViewModel.RateReviewVM 
    { 
     ReviewId = Model.Id, 
     RatingList = new SelectList(Enumerable.Range(1, 10)) 
    }; 
    Html.RenderPartial("_RatingPartial", newRating); 
} 

so dass die Eigenschaft ausgefüllt ist, aber da Sie bereits eine GET-Methode haben, dann wäre es besser, zu verwenden, um die RenderAction() Methode, die die Server-Methode

tut nennen 10
@{ Html.RenderAction("Rating", yourControllerName, new { id = Model.Id }); } 

Hinweis Ich nehme an, dass Ihre Methode tatsächlich public ActionResult Rating(Guid id) ist, da der aktuelle Code eine Ausnahme auslösen würde, da id nicht deklariert wird.

Das wird jedoch nicht alle Ihre Probleme lösen, da die POST-Methode die Überprüfung zurückgibt ModelState ist ungültig (wie es sollte), aber es ist eine andere Ansicht von Ihrem aktuellen. Es wird auch eine Ausnahme ausgelöst, weil Sie die Eigenschaft RatingList nicht erneut auffüllen.

Der richtige Ansatz, um dies zu lösen, ist ein View-Modell für Review, das ein anderes Ansichtsmodell für einen Kommentar enthält.

public class ReviewVM 
{ 
    ... properties of review including property for collection of existing commnets 
    public CommentVM Comment { get; set; } // for generating a new comment form 
} 

und in der Review.cshtml Ansicht, fügen die Form zum neuen Kommentar zu erzeugen, und nach zurück zu sich auf ein Verfahren, das ReviewVM als Parameter hat. Wenn ModelState dann ungültig ist, füllen Sie die Eigenschaften von ReviewVM basierend auf seiner ID erneut auf und füllen Sie die Eigenschaft RatingList der Eigenschaft Comment erneut auf. Wenn Sie dem Benutzer erlauben möchten, mehrere Kommentare für eine Überprüfung hinzuzufügen, können Sie alternativ ein Dialogfeld zum Hinzufügen eines neuen Kommentars verwenden und ajax zum Bereitstellen des Formulars verwenden.

1

Verwenden ViewBag für Ihren dropdrownlist und es wird für PartialView zu arbeiten. und dann brauchst du ViewModels nicht. Es ist in Ordnung, mit Ihren Modellklassen zu arbeiten.

Erste hinzufügen CreateRate Aktion Reviews-Controller

public ActionResult CreateRate(RateReview rate) 
    { 
     if (ModelState.IsValid) 
     { 
      rate.Id = Guid.NewGuid(); 
      db.RateReviews.Add(rate); 
      db.SaveChanges(); 
      return RedirectToAction("Details", "Reviews", new { id = rate.ReviewId }); 
     } 

     return View(); 
    } 

Ändern Details Aktion ein viewbag Daten wie unten

public ActionResult Details(Guid? id) 
{ 

    Review review = db.Reviews.Find(id); 
    ViewBag.RatingList = new SelectList(Enumerable.Range(1, 10)); 

    return View(review); 
} 

Ändern Sie bitte Ihre PartialView wie unten erstellen CreateRate Aktion zum Ziel, fügen Sie ein HiddenFor Helfer für ReviewId und modifiziere Dropdownliste, um von ViewBag zu lesen. Ich benutze RateReview Modell statt Ihrem Ansichtsmodell

@model WebApp.Models.RateReview 


@using (Html.BeginForm("CreateRate", "Reviews")) 
{ 
@Html.AntiForgeryToken() 

<div class="form-horizontal"> 
    <h4>RateReview</h4> 
    <hr /> 
    @Html.ValidationSummary(true, "", new { @class = "text-danger" }) 

    @Html.HiddenFor(model => model.ReviewId) 

    <div class="form-group"> 
     @Html.LabelFor(model => model.SelectedRating, htmlAttributes: new { @class = "control-label col-md-2" }) 
     <div class="col-md-10"> 
      @Html.DropDownListFor(model => model.SelectedRating, (ViewBag.RatingList as SelectList), new { htmlAttributes = new { @class = "form-control" } }) 
      @Html.ValidationMessageFor(model => model.SelectedRating, "", new { @class = "text-danger" }) 
     </div> 
    </div> 

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

am Ende Ihrer Details View ist gerade fein:

@model WebApp.Models.Review 

@{ 
ViewBag.Title = "Details"; 
} 

@{ 
    var newRating = new WebApp.Models.RateReview { ReviewId = Model.Id }; 

    Html.RenderPartial("_RatingPartial", newRating); 

} 


<h2>Details</h2> 

<div> 
<h4>Review</h4> 
<hr /> 
... 
Verwandte Themen