Child actions are not allowed to perform redirect

2019-02-27 16:05发布

问题:

I'm trying to load my partial view with some data from database, but I'm getting following issue when I run the application:

Child actions are not allowed to perform redirect actions.

I don't know why this is happening because I'm pretty new with MVC technology.

Here is my PartialViewResult method in a controller:

public PartialViewResult UnReadEmails()
{
   if (User.Id != null)
   {
      List<Emails> resultList = EmailController.GetUnreadEmailsByUserId(User.Id);
       return PartialView("~/Views/Emails/_UnReadEmails.cshtml", resultList);
   }
   return PartialView("Error, not found!");
}

And here is my partialview itself, it is called _UnReadEmails (as you can see I'm displaying here info about sender and email body), PartialView is retrieving list of Emails that I'm sending to from my Controller

@model IEnumerable<Emails>

foreach (var item in Model)
{
    <li>
        <a>
            <span>
               <span>@item.EmailSender</span>
               <span class="email">
                     @item.Body;
               </span>
        </a>
    </li>
}

After I tried to load my partial view on this way:

@Html.Action("UnreadEmails", "Message")

I started to receive following issue that I mentioned in my Title,

I already tried few things to solve this like changing @Html.Action("UnreadEmails", "Message") to @Url.Action("UnreadEmails", "Message") etc etc but that didn't solve my issue.

EDIT: It allways breaks on this line (on view) :

@Html.Action("UnreadEmails", "Message")

It never goes into code behind..

After Chris suggestion I added [AllowAnonymous] on the top of the method:

[AllowAnonymous]
public PartialViewResult UnReadEmails()
{
   if (User.Id != null)
   {
      List<Emails> resultList = EmailController.GetUnreadEmailsByUserId(User.Id);
       return PartialView("~/Views/Emails/_UnReadEmails.cshtml", resultList);
   }
   return PartialView("Error, not found!");
}

EDIT EDIT EDIT:

Interesting fact is that whatever I wrote in my Controller's method and even if I comment all code, it will still break on a View, that means it will never came into a Controller's method. I put breakpoing there at the begining of the UnReadEmails method and it was never hitted, it allways breaks on a View!

回答1:

The error is pretty explicit. Child actions cannot issue redirects. This is because, while child actions look like regular actions, they are in fact rendered in a separate process and cannot modify the actual response (which a redirect would require).

In your actual child action code, you're not returning a redirect, so that means you must have an action filter being applied to the child action that is issuing the redirect. In particular, you should avoid using things like Authorize or RequireHttps on child actions, as those work by using redirects, which again, a child action cannot do. If the child action is in a controller that is decorated with Authorize, it should be marked with AllowAnonymous.



回答2:

Usually it happens when child Action has errors, because exception gets thrown and MVC trying redirect user to error page. In your case it is trying to find view named "Error, not found!", which probably you don't have. Try run Action as itself first, and check if logic works. Then put your view _UnreadEmails.cshtml in Manage Controller Views folder, and modify the code:

public PartialViewResult UnReadEmails()
{
   if (User.Id != null)
   {
      List<Emails> resultList = EmailController.GetUnreadEmailsByUserId(User.Id);
       return PartialView("_UnReadEmails", resultList);
   }
   return PartialView("_UnReadEmails" new List<Emails>());
}

Sometimes empty List means that nothing was found. OR:

public ActionResult UnReadEmails()
{
   if (User.Id != null)
   {
      List<Emails> resultList = EmailController.GetUnreadEmailsByUserId(User.Id);
       return PartialView("_UnReadEmails", resultList);
   }
   return Content("Error, not found!");
}


回答3:

Hi you may try by changing this line @Html.Action("UnreadEmails", "Message") to like this @{Html.Action("Category","Home");}

if the above doesnt work there are three other ways to render the partial view in mvc. those are

Html.RenderPartial  
Html.RenderAction
Html.Partial

you make use any one of the above and get your solution.

Good example with comparision can be found here:http://www.dotnettricks.com/learn/mvc/renderpartial-vs-renderaction-vs-partial-vs-action-in-mvc-razor

Hope it was helpful,kindly let me know your thoughts or feedbacks

Thanks Karthik



回答4:

At the end I decided to skip my PartialViewResult method from a controller and do it on another way, because I've allready lost 2 days trying to find an answer and it wasn't there, but something else seems to be working, and it was this:

{@Html.RenderPartial("~/Views/Emails/_UnReadEmails.cshtml",EmailController.GetUnreadEmailsByUserId(User.Id))}

What I did there was next, I called directly GetUnreadEmaisByUserId method from my BussinesLogic part, and everything worked like charm.

And what we might do here to make this solution better is next:

In case we dont have a "main model" we could store that in a ViewBag, calling this from a MessageController/Email controller method

ViewBag.lstUnreadEmail‌s = E‌​mailController.Get‌‌​​Un‌​readEmailsByUserId(U‌​ser.Id);
And in the View use this

{@Html.RenderPartial("~/Views/Emails/_UnReadEmails.cshtml",ViewBag.lstUnreadEmail‌​s}