Home » Asp.netRSS

Masterpage Dropdown list

I have a dropdownlist on my master page which contains entries whose ID's basically drive the rest of the site.

When a user chooses an item in the dropdown list, the value of the dropdownlist is stored in a session and that value is used to pull the correct data.


My problem is that im getting the error "Child actions are not allowed to perform redirects". I have a base controller, which contains two methods that render the contents of my model for the masterpage.

    public class MasterPageController : Controller
    {
        public ActionResult DropdownList(){
            MasterViewModel m = new MasterViewModel ... shortened.
            return View(m);
        }

        [HttpPost]
        public ActionResult DropdownList(FormCollection collection)
        {
            //removed, basically just sets the session id, gets the model
            return RedirectToAction("Default", "Home", new { id = collection.Get("IDList").ToInt32() });
        }
    }

The dropdown list is rendered in my masterpage like so:

<%Html.RenderAction("DropdownList"); %>

This works fine, I can set the dropdown, it picks up the right values just fine.... Until I make a post that is not from the dropdownlist form.

So whats happening is I have a view in which im creating some data, saving it. During the creation process, my model did not pass validation, so I had to return back to the page and display the errors. When i return the View, it goes through the masterpage and hits the RenderAction method. Inside this its hitting the HttpPost action and trying to redirect while the view is currently rendering.


How do I get around this? Am I on the right track for having a persisted dropdownlist on a masterpage?

 

12 Answers Found

 

Answer 1

Do you have your DropDownList in it's own form  tag? 

 

Answer 2

Yes I do, it points to the DropdownList with HttpPost attribute in my base  controller.

 

Answer 3

I have created a simple test project to reproduce the issue. Using the default MVC 2 Application, I modified the Master page's RenderPartial method  for the Login control to this.


<div id="logindisplay">
       <% Html.RenderAction("ErrorTest", "Home"); %>
</div>


In the HomeController, I created two methods  that will do stuff when my dropdownlist  is used.

        public  ActionResult ErrorTest()
        {
            List<SelectListItem> items = new List<SelectListItem>();

            for (int i = 0; i < 10; i++)
                items.Add(new SelectListItem
                {
                    Text = i.ToString(),
                    Value = i.ToString()
                });
            TestViewModel test = new TestViewModel();
            test.DropDownItems = items;
            return  View(test);
        }

        [HttpPost]
        public ActionResult ErrorTest(string test)
        {
            //cRASH!
             return RedirectToAction("Index");
        }


I then created a ViewModel to return to my view

    public class  TestViewModel
    {
        public IEnumerable<SelectListItem> DropDownItems { get; set; }
    }



I created the User control (ErrorTest.ascx)

<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<MvcApplication2.Models.TestViewModel>" %>
<div>
    <% using (Html.BeginForm("ErrorTest", "Home", FormMethod.Post, new { id = "ErrorList" }))
        { %>
        <span style="color: #333; font-size: 14px; font-weight: bold;">Select somthing: </span>
        <%= Html.DropDownList("Errors", Model.DropDownItems, " -- error  DropDown! --", new { style = "width:200px;", onchange = " $(\"#ErrorList\").submit()" })%>
    <%} %>
</div>



And now I can create a form  on any view, submit the form, and the error is reproduced.

I dont get why when there is a post, the public ActionResult ErrorTest(string test) method is getting picked up. I didnt post  to this?


 

Answer 4

The point is that you cannot do a redirect  to another page  form an action method  od a control that is in the master  page.....The flow of control can only be decided by the principal view! A redirect is actually a redirec involving also the browser, not simply a call of another method. MVC don't know how to translate this redirect! To do a redirect you need to specify a full page not only a piece of master page. Substitute the redirect with a simple method call of a non-action method that is used by the two actions  that need it.

 
 

Answer 6

francesco abbruzzese:

The point is that you cannot do a redirect  to another page  form an action method  od a control that is in the master  page.....The flow of control can only be decided by the principal view! A redirect is actually a redirec involving also the browser, not simply a call of another method. MVC don't know how to translate this redirect! To do a redirect you need to specify a full page not only a piece of master page. Substitute the redirect with a simple method call of a non-action method that is used by the two actions that need it.

 

If I do this, the RenderAction will not render  anything if it's not returning view  information.


assafg2:

i think that you are looking for a partial view

try this link

http://jeffreypalermo.com/blog/asp-net-mvc-and-the-templated-partial-view-death-to-ascx/ 


Do you have anymore indepth examples of this? From what ive been reading, partial views only display data  and do not accept post  data. I also need to pull  dynamic content and I cannot find any examples that demonstrate partial views beyond the display  of text/ViewData.

 

Answer 7

cepS:
If I do this, the RenderAction will not render  anything if it's not returning View information.


The problem  is tah it returns NOTHING in any case it just say to the browser to go to another page  to display  something....The point that the vie you redirect  to is not able to render a full page.

 

Answer 8

It is likely that all of your other form  posts use the basic Html.BeginForm without any parameters. If that is the case, then they will execute the DropDownList action  in your base  controller because of the "POST." To correct  this, you would need to specify the action for every form (Html.BeginForm("MyAction")).

You might be able to use a custom selector to only match your DropDownList action when that specific form is executed while ignoring all other POSTS. Look into creating a custom selector from ActionNameSelectorAttribute.

 

Answer 9

After thinking about it for a bit, you really do need to go with rendering a partial view  instead of an action. You can provide the data  necessary for the dropdownlist  in the constructor of your base controller. The following is a quick example:

Controller:

    public  abstract class  BaseController : Controller
    {
        public BaseController()
        {
            var items = new List<SelectListItem>
                            {
                                new SelectListItem {Text = "Test 1", Value = "1"},
                                new SelectListItem {Text = "Test 2", Value = "2"}
                            };
            ViewData["DemoDropDownListData"] = items;
        }

        [HttpPost]
        public ActionResult DropDownList(int id)
        {
            return  RedirectToAction("Index", "Home");
        }
    }


Site.Master:

<% Html.RenderPartial("DropDownList", ViewData["DemoDropDownListData"]); %>


DropDownList.ascx:

<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<IEnumerable<SelectListItem>>" %>
    <% using(Html.BeginForm("DropDownList", "Home", FormMethod.Post, new { id = "DropDownListTest"})) { %>
    <%: Html.DropDownList("id", Model, new { onchange = "$('#DropDownListTest').submit()"}) %>
    <% } %>


 

 

Answer 10

I tried this solution by adding my model  to ViewData and when I submit the form  I get a 404, cant find the Home/Dropdownlist URL.

grrr

 

Answer 11

I tested the previously mentioned solution and it worked as expected. Show the code for your controller, view, and model. I'll try to reproduce your issue and see what's happening.

 

Answer 12

Well I got it working, i was using the BaseController in the form, that was why it wasn't finding it.

Thanks for the help everyone!.

 
 
 

<< Previous      Next >>


Microsoft   |   Windows   |   Visual Studio   |   Follow us on Twitter