64

How can I create an individual controller and model for a partial view? I want to be able to place this partial view any where on the site so it needs it's own controller. I am current rendering the partial as so

@Html.Partial("_Testimonials")
brenjt
  • 15,997
  • 13
  • 77
  • 118
  • http://www.c-sharpcorner.com/article/html-action-and-html-renderaction-in-Asp-Net-mvc/ – Iman Aug 28 '17 at 07:41

6 Answers6

119

Why not use Html.RenderAction()?

Then you could put the following into any controller (even creating a new controller for it):

[ChildActionOnly]
public ActionResult MyActionThatGeneratesAPartial(string parameter1)
{
    var model = repository.GetThingByParameter(parameter1);
    var partialViewModel = new PartialViewModel(model);
    return PartialView(partialViewModel); 
}

Then you could create a new partial view and have your PartialViewModel be what it inherits from.

For Razor, the code block in the view would look like this:

@{ Html.RenderAction("Index", "Home"); }

For the WebFormsViewEngine, it would look like this:

<% Html.RenderAction("Index", "Home"); %>
George Stocker
  • 57,289
  • 29
  • 176
  • 237
  • 4
    the only thing with renderaction is of course that it makes a 2nd request, whereas renderpartial does it as part of the same initial request. 9/10 times won't matter but worth noting. see http://stackoverflow.com/questions/719027/renderaction-renderpartial for a little background – jim tollan Jun 09 '11 at 08:19
  • In vbhtml I get the error "Expression does not produce a value" on `@Html.RenderAction("MyActionThatGeneratesAPartial", "Home")` – KyleMit Oct 29 '14 at 23:17
  • @kylemit is your code like this? `@{ Html.RenderAction("Index", "Home"); }` – George Stocker Oct 29 '14 at 23:18
  • @GeorgeStocker, nope. You're right. The trick was to [put it inside of a code block](http://stackoverflow.com/q/11052331/1366033) – KyleMit Oct 29 '14 at 23:20
  • 1
    This worked out as the perfect solution for me. I am using the return PartialView() to render a Partial View that contains a dropdownlist for the site header in the _Layout View like so: `PartialView("_AccountsDDL", model);` – landsteven Apr 29 '16 at 15:13
10

If it were me, I would simply create a new Controller with a Single Action and then use RenderAction in place of Partial:

// Assuming the controller is named NewController
@{Html.RenderAction("ActionName", 
                     "New", 
                      new { routeValueOne = "SomeValue" });
}
RuudvK
  • 635
  • 5
  • 9
Justin Niessner
  • 242,243
  • 40
  • 408
  • 536
  • 3
    In your code snippet wouldn't it be better to use `RenderAction` as you described in your answer? – Martin Nov 14 '14 at 13:04
  • Have to say this is the only example I have found thus far where the partial encapsulates its own functionality so I can put a single line anywhere and have it work with out modifications for other views/controllers etc – djack109 Jun 20 '17 at 07:14
10

It does not need its own controller. You can use

@Html.Partial("../ControllerName/_Testimonials.cshtml")

This allows you to render the partial from any page. Just make sure the relative path is correct.

Chris Woolum
  • 2,854
  • 20
  • 20
  • 4
    why would this get voted down? The assumption was that a separate controller was needed in order to render a partial on any page of the site. This is not true. You can render a partial from any controller. This ia a valid answer – Chris Woolum Jun 09 '11 at 01:30
  • 3
    Just guessing, whoever downvoted you probably wanted a viewmodel to go with the partial view, and leaving the creation of that to a seperate dedicated controller. Your example works great with no viewmodel, but forces the current (all) controllers to create/populate a viewmodel and pass it to the partial – Per Hornshøj-Schierbeck Jan 07 '14 at 13:39
  • don't forget the extension: Html.Partial("../ControllerName/_Testimonials.cshtml") – JoshYates1980 Sep 04 '14 at 19:43
4

The most important thing is, the action created must return partial view, see below.

public ActionResult _YourPartialViewSection()
{
    return PartialView();
}
Uwe Keim
  • 39,551
  • 56
  • 175
  • 291
Wen Chen
  • 49
  • 2
3

You don't need a controller and when using .Net 5 (MVC 6) you can render the partial view async

@await Html.PartialAsync("_LoginPartial")

or

@{await Html.RenderPartialAsync("PartialName");}

or if you are using .net core 2.1 > you can just use:

<partial name="Shared/_ProductPartial.cshtml"
         for="Product" />
GoldenAge
  • 2,918
  • 5
  • 25
  • 63
0

Html.Action is a poorly designed technology. Because in your page Controller you can't receive the results of computation in your Partial Controller. Data flow is only Page Controller => Partial Controller.

To be closer to WebForm UserControl (*.ascx) you need to:

  1. Create a page Model and a Partial Model

  2. Place your Partial Model as a property in your page Model

  3. In page's View use Html.EditorFor(m => m.MyPartialModel)
  4. Create an appropriate Partial View
  5. Create a class very similar to that Child Action Controller described here in answers many times. But it will be just a class (inherited from Object rather than from Controller). Let's name it as MyControllerPartial. MyControllerPartial will know only about Partial Model.
  6. Use your MyControllerPartial in your page controller. Pass model.MyPartialModel to MyControllerPartial
  7. Take care about proper prefix in your MyControllerPartial. Fox example: ModelState.AddError("MyPartialModel." + "SomeFieldName", "Error")
  8. In MyControllerPartial you can make validation and implement other logics related to this Partial Model

In this situation you can use it like:

public class MyController : Controller
{
    ....
    public MyController()
    {
    MyChildController = new MyControllerPartial(this.ViewData);
    }

    [HttpPost]
    public ActionResult Index(MyPageViewModel model)
    {
    ...
    int childResult = MyChildController.ProcessSomething(model.MyPartialModel);
    ...
    }
}

P.S. In step 3 you can use Html.Partial("PartialViewName", Model.MyPartialModel, <clone_ViewData_with_prefix_MyPartialModel>). For more details see ASP.NET MVC partial views: input name prefixes