36

My case looks like this:

Model:

public class Book
{
    public string Id { get; set; }

    public string Name { get; set; }
}

public class Comment
{
    public string Id { get; set; }

    public string BookId { get; set; }

    public string Content { get; set; }    
}

Controller:

public IActionResult Detail(string id)
{
    ViewData["DbContext"] = _context; // DbContext

    var model = ... // book model

    return View(model);
}

View:

Detail view:

@if (Model?.Count > 0)
{
    var context = (ApplicationDbContext)ViewData["DbContext"];
    IEnumerable<Comment> comments = context.Comments.Where(x => x.BookId == Model.Id);

    @Html.Partial("_Comment", comments)
}

Comment partial view:

@model IEnumerable<Comment>

@if (Model?.Count > 0)
{
    <!-- display comments here... -->
}

<-- How to get "BookId" here if Model is null? -->

I've tried this:

@Html.Partial("_Comment", comments, new ViewDataDictionary { { "BookId", Model.Id } })

Then

@{
    string bookid = ViewData["BookId"]?.ToString() ?? "";
}

@if (Model?.Count() > 0)
{
    <!-- display comments here... -->
}

<div id="@bookid">
    other implements...
</div>

But error:

'ViewDataDictionary' does not contain a constructor that takes 0 arguments

When I select ViewDataDictionary and press F12, it hits to:

namespace Microsoft.AspNetCore.Mvc.ViewFeatures
{
    public ViewDataDictionary(IModelMetadataProvider metadataProvider, ModelStateDictionary modelState);
}

I don't know what are IModelMetadataProvider and ModelStateDictionary?

My goal: Send model comments from view Detail.cshtml to partial view _Comment.cshtml with a ViewDataDictionary which contains BookId.

My question: How can I do that?

5
  • 2
    This is not an answer but passing the dbcontext to the view seems just wrong and against the idea of mvc. Why don't you just have a model property for the data you fetch in the view using the db context? Commented Nov 8, 2016 at 6:30
  • @WiktorZychla Oh, sorry about that. I would expand the case. In Detail.cshtml. I have to refer many models: Book, BookDetail, UserProfile, Comment. It's so hard if you compress all of them to a model, then calling it in the view. Also, in asp.net core, there is no constructor for class ApplicationDbContext with 0 parameter by default. So, I cannot use using (var db = new ApplicationDbContext){} in the View like mvc 5. Commented Nov 8, 2016 at 6:36
  • 1
    You Book model should have a ICollection<Comment> so all the comments are loaded when you get the book. And passing db context to the view is awful practice - you controller is responsible for getting the data as passing it to the view Commented Nov 8, 2016 at 6:36
  • @StephenMuecke Exactly what I'm looking for. That really helps! Many thanks! Commented Nov 8, 2016 at 6:48
  • As always, create a view model representing what you want to display in the view (e.g. it might include a string UserName property to display the nae of the user) Then in the GET method, initialize an instance of that view model and set its properties and pass the view model to the view. Commented Nov 8, 2016 at 6:57

3 Answers 3

53

Another way to use this is to pass the ViewData of the current view into the constructor. That way the new ViewDataDictionary gets extended with the items you put in using the collection initializer.

@Html.Partial("MyPartial", new ViewDataDictionary(ViewData) { { "BookId", Model.Id } })
Sign up to request clarification or add additional context in comments.

Comments

22

Use the following code to create a ViewDataDictionary

new ViewDataDictionary(new Microsoft.AspNetCore.Mvc.ModelBinding.EmptyModelMetadataProvider(), new Microsoft.AspNetCore.Mvc.ModelBinding.ModelStateDictionary()) { { "BookId", Model.Id } }

Comments

9

On .NET Core I use ViewDataDictionary with a parameter, like:

@Html.Partial("YourPartial", new ViewDataDictionary(ViewData) { { "BookId", Model.Id } })

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.