Reputation: 3515
I have a _Layout.cshtml files as a partial view as header on each main view.
I would like to define a Select element on the _Layout and pass some data to the partial view using ViewBag so that the data is populated on the view and can later be submitted.
My questions are:
Thanks!
Upvotes: 0
Views: 8714
Reputation: 14716
There are possibly a few misunderstandings about how _layout.cshmtl and partial views work:
_layout.cshtml is not a partial view. It is the layout template used by all your pages. It is kind of the "outer" of the page. It is automatically applied (except if you set Layout = null
). A partial view in turn is the "inner" of the page. You call it explicitly from your page using @Html.Partial
.
Even though your page is rendered by multiple views - the actual view, the layout, maybe some partial views - it is still the result of a single controller action. (Except if you use @Html.Action
for rendering partial "actions"). Also, the page rendered is a single HTML page, that is, any forms on the page are simply HTML forms.
Therefore, the answer to "where is the ActionResult function defined" is: In the action that you want your page to be rendered for.*
The answer to "Which action should be used to accept the HttpPost command" is the same as if the form was on your page: You can define an arbitrary action on an arbitrary controller for receiving the form. You just need to refer to that action when you render the form:
@using (Html.BeginForm("action", "controller")) { ... }
*) If you want to prevent having to build the select list in each and every controller action that relies on _layout, you could conceivably use @Html.Action
. That is, you define a "partial action" which is nothing else than a controller action that returns a PartialView()
and a partial view to render the model from that action. Then you can use that partial action to build the select list.
However having read some news about ASP.NET vNext, partial actions seem not to be liked to much by the community and in vNext there will be another way to achieve the same.
Still if you want to go this way this enables you to separate the logic for your dropdown (language? user menu?) from your other actions and views:
class UserController
{
PartialViewResult UserMenuDropdown()
{
return PartialView(BuildUserMenuFrom(.....));
}
[Post]
ActionResult PostUserMenu()
{
// do whatever you want once the form is posted
}
}
In your _layout you call the partial action:
@Html.Action("UserMenuDropdown", "User")
And in the view for UserMenuDropdown you render the form:
@using (Html.BeginForm("PostUserMenu"))
{
@Html.DropDownListFor(m => m.UserMenuSelectList)
}
This way your dropdown list becomes a "first class member", with its own controller action, main view, and model. You don't need a ViewBag for this, and you don't have to build the select list in each and every controller action.
Upvotes: 2
Reputation: 2727
What I suggest is to make a base controller class. Inherit all your controllers from it. The code to render the data for the layout, can lie in it's constructor, or some other common function that all your controllers can use as children of this base class.
public class BaseController : System.Web.Mvc.Controller
{
public BaseController()
{
// This code will run for all your controllers
ViewBag.MyData = "SomeData";
}
}
About your question:
What do I do if I want to submit a form on the partial view? Where and which action should be defined/used to accept the HttpPost command?
You can just put the controller name on your form:
@using (Html.BeginForm("ActionName", "Controller"))
Upvotes: 3