2

I'am using ASP.NET MVC 4 with EF, I have a PostController with the Index and Create views. I would like to have both on the same page for adding a post, and visualize it on the same page. How can I do it ?

Thanks for your advices

___EDIT__

Controller :

        public ActionResult Index()
        {
            return View(db.Posts.ToList());
        }

        [HttpGet]
        public ActionResult Create()
        {
            return PartialView("_Create", **Here I can't declare model**);
        }

        [HttpPost]
        public ActionResult Create(FormCollection values)
        {
            var post = new Post();
            TryUpdateModel(post);

            if (ModelState.IsValid)
            {
                /** somme code **/

                db.Posts.Add(post);
                db.SaveChanges();
                return RedirectToAction("Index");
            }
            return View("_Create", post);
        }

My _Create partial view :

@model MyProject.Models.Post

<h2>Create</h2>

@using (Html.BeginForm()) {
    @Html.ValidationSummary(true)

    /**some stuff **/
}

my Index View :

@model IEnumerable<MyProject.Models.Post>

@{
    ViewBag.Title = "Index";
}

<p>
    /** some stuff **/
</p>

@Html.Partial("_Create", **Here I can't declare model**)

And my Post Model :

public int PostId { get; set; }    
public int UserId { get; set; }       
public string Content { get; set; }

It tells me that "The model item passed into the dictionary is of type ‘System.Collections.Generic.List`1[MyProject.Models.Post]’ but this dictionary requires a model item of type ‘MyProject.Models.Post‘.

tereško
  • 58,060
  • 25
  • 98
  • 150
Alternative
  • 187
  • 2
  • 3
  • 13

1 Answers1

4

It really depends on how your code looks right now. If you have a separate Create action method returning a PartialView, like so:

[HttpGet]
public ActionResult Create()
{
    // Do stuff here to populate your model, if necessary
    return PartialView("_Create", model);
}

Then in your view you would use Html.RenderAction() where you want the _Create partial view to be displayed:

<div id="IndexViewStuff">
    <p>Some stuff in your normal Index view.</p>
    @{Html.RenderAction("Create", "Post");}
</div>

If you don't have a separate action method for Create and just have a partial view to make things cleaner, then simply using Html.Partial() in your Index view will do the trick:

@Html.Partial("_Create") // If your _Create partial does not require a model
@Html.Partial("_Create", Model.CreateViewModel) // If it does require a model

Update

After looking through your code, there are two ways you can do it (I'll show you both). Your problem occurs because you're passing a list of posts to your Index view while your _Create partial view requires a single Post model. Since you aren't explicitly passing a model to the partial view when you're calling it, it automatically tries to use the model in the Index view (your list of posts). The first way to solve the problem requires minimal changes to your code.

Change your Create action method as follows:

[HttpGet]
public ActionResult Create()
{
    // You have to pass a new Post
    return PartialView("_Create", new MyProject.Models.Post());
}

Then in your Index view, use:

@{Html.RenderAction("Create", "Post");}

The second method is to use a view model that exposes the list of posts to display on the Index view, and also has an "empty" Post model that can be used to create a new post in the _Create partial view. I prefer this method, but it's your call.

Your view model:

public class MyViewModel
{
    public IEnumerable<Post> Posts { get; set; }
    public Post CreatePost { get; set; }
}

Your Index action method:

public ActionResult Index()
{
    MyViewModel model = new MyViewModel()
    {
        Posts = db.Posts.ToList(),
        CreatePost = new MyProject.Models.Post()
    };

    return View(model);
}

Your Index view:

@model The.Namespace.MyViewModel

@{
    ViewBag.Title = "Index";
}

@foreach (var post in Model.Posts)
{
    <p>post.Content</p> // Or however you want to display your posts
}

@Html.Partial("_Create", Model.CreatePost) // Pass the correct model

Your _Create partial view will remain the same.

HTX9
  • 1,717
  • 3
  • 15
  • 27
  • Hello, thanks for your explanations. I've updated my post with some code. I think i need to create a ViewModel like in the case you've told 'cause it does require a model. I don't know how to use a ViewModel, what i need to declare into it ? My index view use IEnumerable whereas my _create doesn't use IEnumerable, if I understand the error, that is where the conflict is..sorry for my english also... – Alternative Dec 13 '12 at 21:55
  • Thanks again for the precision of your explanation, i better understand how it's work now. However, i have some issues with both methods. First one works, my partial view is well displayed but when i click on "Create" it returns me `child actions are not allowed to perform redirect actions`. But my data are well writing in the db and are displayed when i re-execute. For the second, I don't really understand the link between the Index action method, the viewmodel and the create method... I've tried it, and my partial view is well displayed but nothing appens when i click create. – Alternative Dec 14 '12 at 01:31
  • @Alternative For the first problem, try using `return RedirectToAction("Index", "Post");` in your `HttpPost Create` action method. For the second, are you using the same partial view for `_Create` as you used when you tried the first method? – HTX9 Dec 14 '12 at 02:32
  • For the first method, same problem even with the argument "Post". And yes I'm using the same `_Create` partial view. – Alternative Dec 14 '12 at 02:54
  • @Alternative Sorry I can't really help you more without digging into your code, but you might want to see http://stackoverflow.com/questions/2056421/why-are-redirect-results-not-allowed-in-child-actions-in-asp-net-mvc-2 – HTX9 Dec 14 '12 at 02:59
  • thanks anyway, you were a great help. the second method bother me, it almost works, it's just my data which seem to not be added in some way. Why declare `CreatePost = new Post()` in the Index Action method ? Is it just for the display ? I don't understand why we do not use the postviewmodel in the create action method.. – Alternative Dec 14 '12 at 03:29
  • If you want to go down the path of making the Index controller perform actions other than displaying an index of data, what about isolating each piece of functionality (such as edit) into a separate Controller which returns a PartialView and posting with AJAX? Have a look at http://ricardocovo.com/2011/04/03/asp-mvc3-editing-records-with-jqueryui-dialogs-and-ajaxforms/. This is a bit more work, but it will lead to better user experience and will mean it will mean you already have an Edit controller defined if you decide to make it a completely separate view later. – Aaron Newton Dec 16 '12 at 11:27
  • Regarding the error (child actions are not allowed to perform redirect actions). Try commenting the return RedirectToAction() in your Create Method. It worked for me. – Baso Apr 25 '16 at 12:27