My PartialView is causing my application to breakdown everytime - c#

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 on another post 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!
EDIT AFTER MAURIZIO suggestion to change it to #Html.RenderPartial
Than I received following issue:
The partial view 'UnReadEmails' was not found or no view engine
supports the searched locations. The following locations were
searched: ~/Views/Dashboard/UnReadEmails.aspx
~/Views/Dashboard/UnReadEmails.ascx ~/Views/Shared/UnReadEmails.aspx
~/Views/Shared/UnReadEmails.ascx ~/Views/Dashboard/UnReadEmails.cshtml
~/Views/Dashboard/UnReadEmails.vbhtml
~/Views/Shared/UnReadEmails.cshtml ~/Views/Shared/UnReadEmails.vbhtml
EDIT:
Compiler Error Message: CS0120: An object reference is required for the non-static field, method, or property 'MessageController.UnReadEmails()'
I tried to make UnReadEmails() as static but than I received following error :
Error 1 An object reference is required for the non-static field,
method, or property 'System.Web.Mvc.Controller.PartialView(string,
object)' ...Controllers\Message\MessageController.cs

Since your partial view is not in the Shared folder you need to provide the full path
{#Html.RenderPartial("~/Views/Emails/_UnReadEmails.cshtml")}
Since that view needs the list of emails you need to add that as parameter
{#Html.RenderPartial("~/Views/Emails/_UnReadEmails.cshtml",EmailController.GetUnreadEmailsByUserId(User.Id))}
The best aproach would be to create a property in the Model (List<Emails> lstUnreadEmails) and load that list of emails in a method of the MessageController, so that the information is ready for the partial to be render with this instruction:
{#Html.RenderPartial("~/Views/Emails/_UnReadEmails.cshtml",Model.lstUnreadEmails)}
In case you dont have a "main model" you could store that in a ViewBag, calling this from a MessageController 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)}

Related

Loading a partial view dynamically and loading index from controller

I am at a loss on how to do this. I've tried every search I can think of. Any help/direction would be greatly appreciated.
The customer wanted to be able to load a partial view dynamically from a wysiwyg editor. So, I made a method in the controller that searches for a special tag that gets the name of the partial view. Got that to work fine. Now the customer wants to load and post data to/from the partial view.
I was able to get it loaded by doing this - finalhtml += PartialView("~/Views/Global/Partials/" + commandContents + ".cshtml").RenderPartialViewToString();
If I name the controller the exact name of the partial view plus controller ie: SamplePartialController, I can get the view post back to the controller, BUT I can't figure out how to load an initial index method on the partial no matter what I try.
It would be nice if I could define the initial index method and controller name programmatically, just not seeing a way.
I am fairly new to mvc, been doing asp.net for over a decade, and this may be very obvious, but I'm just not finding a way. Thanks!
Not sure I understand clearly the issue. I also had a lot of troubles working with partial views (to post data, to load them back if something wrong happened in the post action...).
It seems like you want to fill your partial view if some parameters are here when loading the index.
In the Controller.Index (or where you get your parameters) you can assign some ViewModel values, or use the ViewBag/ViewData.
In the index view, you can call where you need the RenderPartialAsync() based on your parameters setted previously
this.ViewData["error"] = Model.Error;
this.ViewData["partialGuid"] = Guid.NewGuid();
this.ViewData["foo"] = bar;
await Html.RenderPartialAsync("_PartialViewName", Model.PartialViewModel, this.ViewData);
And use your partial view the same way you do from an ajax call.
If you need to post data from your partial view, I struggled a lot with some things:
A FormContext is required in the partial view
#if (this.ViewContext.FormContext == null)
{
this.ViewContext.FormContext = new FormContext();
}
If you allow to push multiple times your partial view and post them, making a custom collectionId helps a lot when in the controller post action
#{
var collectionId = $"PartialItems[{this.ViewData["partialGuid"]}].{{0}}";
}
// then later...
<input class="form-control"
data-val="true"
data-val-required="#(string.Format(ApplicationResources.Error_Required, ApplicationResources.FieldFirstName))"
id="#(string.Format(collectionId, "FirstName"))"
name="#(string.Format(collectionId, "FirstName"))"
type="text"
value="#(string.IsNullOrWhiteSpace(Model.FirstName) ? string.Empty : Model.FirstName)" />
<span class="field-validation-valid text-danger"
data-valmsg-for="#(string.Format(collectionId, "FirstName"))"
data-valmsg-replace="true"></span>
// And in your Index ViewModel, something like that to get the collection in the controller post action
public IDictionary<string, PartialViewModel> PartialItems { get; set; }
If you call the new partial view with Ajax, after the first render of the view, reset the jquery validator if needed
$.ajax({
// ...
success: function (res) {
// do your stuff
$('#parentId').prepend(res);
// reinit the validation
$("form").each(function () { $.data($(this)[0], 'validator', false); });
$.validator.unobtrusive.parse("form");
}
});
It is almost everything I can think of that bugged me when dealing the first time with all this partial view things. Hope something here can help you.

ASP.NET MVC - How do I Call a Controller Method from within a View to Redirect to Multiple Other Views?

I am trying to add a single link in my navbar that redirects the user to a different webpage depending on their account type. I am having issues doing this and could use some help.
The Controller code that I am calling looks like this:
public IActionResult Attendance(char accountType)
{
if (accountType.Equals("m") || accountType.Equals("a"))
{
return RedirectToAction("FacultyAttendance");
}
else
{
return RedirectToAction("StudentAttendance");
}
}
public IActionResult StudentAttendance()
{
// More functionality will be added later
return View();
}
public IActionResult FacultyAttendance()
{
// More functionality will be added later
return View();
}
Following this answer for calling the Controller method, I have this code snippet in the View file:
Attendance
This gives me the following error:
Bad Request - Invalid URL
HTTP Error 400. The request URL is invalid.
I also tried following this answer by removing the <%: and %>.
Attendance
If I do this, I just get blank webpage.
My first problem lies in which style I should use for this method call within the View file. Are either of these correct, or should I use something else entirely? Might the issue be with the way I have the Controller code set up?
Any help would be appreciated, as I am new to the MVC framework for ASP.NET.
Edit: The solution I found is a bit different than what I originally posted. I used this tag in my View and got it to work:
<a asp-controller="Home" asp-action="Attendance" asp-route-accountType='s'>Attendance</a>
I also followed ThisGuy's suggestions for improving the code since I had mismanaged some variables and that may have been part of the problem.
accountType is a char, but you are passing a string:
new {accountType = "m"}
Change the Controller to take a string instead of char for accountType.
public IActionResult Attendance(string accountType)
Also, I'd write it like this:
public IActionResult Attendance(string accountType) =>
RedirectToAction(
accountType.Equals("m") ||
accountType.Equals("a")
? nameof(FacultyAttendance)
: nameof(StudentAttendance));

Passing Parameters to PartialView

I have a cshtml file which is reading 2 variables I'm sending it.
It works fine with sending the parameters using ViewDataDictionary from another view using #HTML.Partial. But I am getting 500 errors when I am trying to send the same type of arguments through my function bellow
public ActionResult Refresh(string id){
return PartialView(page,new ViewDataDictionary { { "points" , get_points(id)) } });
}
My #HTML.Partial looks the sameway, the only thing that is different is the PartialView. I have verified in the debugger that my parameters have the same look.
Why is PartialView generating 500 errors and Partial is not?
I was not keeping track in my head of where I was sending the parameters from. I was sending from View To View when I was using ViewDataDictionary. While this time I was trying to send from the controller to the view.
I solved this using ViewData to initiate the variables in the model so that my view could access them.

How to render field in PageEditor when using Template inheritance with Sitecore Glass Mapper

I have the following setup in my solution, described in an earlier post:
How to implement Sitecore Template inheritance with Glass Mapper
I'm able to display the content of inherited fields now. However when I try to edit them in the page editor the EditFrame is not rendered, nothing gets rendered actually. Not sure what I'm still missing. Here's my controller and view:
Controller:
public class NavigationController : Controller
{
// GET: /Navigation/
public ActionResult Index()
{
var context = new SitecoreContext();
var page = context.GetCurrentItem<HomePage>();
return View("/Views/Navigation.cshtml", page);
}
}
View:
#inherits Glass.Mapper.Sc.Web.Mvc.GlassView<Sitecore.Training7.Internet.Core.Models.HomePage>
#if (Model != null)
{
<h3 class="text-muted">Field: #Editable(x => x.NavigationTitle)</h3>
}
When I hit the preview button the value is displayed, I don't see the value in the PageEditor though. What am I still missing here? Any ideas?
This is just a guess based on the HomePage model that you included in your other post, but I think you need to add an ID property to your model. See http://glass.lu/docs/tutorial/sitecore/tutorial05/tutorial05.html
I see your other post now, please add the Id:
[SitecoreId]
Guid Id{ get; }
In page editor mode, sitecore would require the mapped Id to know which item the value belongs to. So you will need to add this to your model too.
If by any chance you are using TDS or something similar - you'll see that the property is added by default in the base class for all model classes by default.

From action to action to _Layout

I have a layout page that displays simple messages to the user.
I have a People Controller with an Index action/view that displays a list of people and I have an Edit action/view for a person.
When the user successfully updates and saves a person's details, I want to redirect from the Edit action to the Index page but display a message such as "The person was successfully updated".
I've tried adding things to the ViewBag but it doesn't persist.
I have a ViewModel Base class, but don't know if/how to set the Index's ViewModel from the Edit action.
How can I achieve this where messages are passed from various places to be used in _Layout?
You can use TempData to accomplish this. Values stored in TempData will only persist across one Http request, making it ideal to store these types of messages.
Edit POST Action
[HttpPost]
public ActionResult Edit(EditPersonModel model)
{
// .. Your code to edit the person ..
TempData["message"] = "The person has been updated.";
return RedirectToAction("Index", "People");
}
Your View
#if (TempData["message"] != null)
{
<p>#TempData["message"]</p> // Displays the message
}
You can build an entire notification system that uses TempData and ViewData (controller extensions, etc), but this is the simplest way to do it.

Categories