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.
Related
Can I run these get and post actions with just single button? I get an id from my view then I just wanna run my post action.
I've already tried to getting id with parameter and put it in session but couldn't do it with one submit button
[HttpGet]
public ActionResult JoinEvent(int id)
{
Session["EventID"] = id;
return View();
}
[HttpPost]
public ActionResult JoinEvent(EventPerson eventPerson)
{
Person per =(Person) Session["Login"];
eventPerson.PersonID = per.PersonID;
eventPerson.EventID = (int)Session["EventID"];
eventPerson.TotalPerson = eventPerson.TotalPerson + 1;
eventManager.Join(eventPerson);
return View();
}
and this is my view
<td class="buy_link">
#Html.ActionLink("Join","JoinEvent","Join",item.EventID,null)
</td>
As what you posted here, it looks like the EventId can be set freely (without any security restrictions) by the client by simply navigating to GET /JoinEvent?id=100.
If security isn't an issue, you can do it by many many ways
Passing the event id to the client, which in turn will give it back to the server.
How ? Here is one way
Passing it as part of EventPerson model, which you will need to add a new property inside of that model.
ActionResult should: return View(new EventPerson { EventId: id })
Decorating view top row (after import statments) with the following #model EventPerson, this will tell the view that now he represents this type. (Which was passed by the GET action)
Now we should decide if we want to pass it back to the server as query string parameter or a body parameter ? Because we're doing a semantic "Insert" action, in most cases the practice asks us to pass it as part of the body. thus, you should use an hidden text box to pass EventId parameter.
#Html.Hidden("EventId", #model.EventId))
"EventId" is the property we want to bind on our POST server action EventPerson newly property. (Point#1)
#model.EventId is the value we took from the server and passed it into the View (Point#2)
Technically you cannot. When you create an anchor tag using action link, it creates a link to the specified URL. When you click on that link that fires a GET request. That will not POST data to the action method. If you need to POST data, you need to either submit a form or you can use Javascript/jQuery to do that. You can collect the data and send it as a POST using Js/jQuery. But just the anchor won't send a POST method.
Refer this
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.lstUnreadEmails = EmailController.GetUnreadEmailsByUserId(User.Id);
And in the View use this
{#Html.RenderPartial("~/Views/Emails/_UnReadEmails.cshtml",ViewBag.lstUnreadEmails)}
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.
I have opened a sample ASP.NET MVC project.
In HomeController I have created a method (action) named MethodA
public ActionResult MethodA()
{
return View();
}
I have right clicked on MethodA and created a new view called MethodA1
Re-did it and created a new view called MethodA2.
How is this magical relationship done? I looked for the config to tell the compiler that views MethodAX are related to action MethodA, but found none.
What view will the controller return when MethodA is called?
The convention is that if you don't specify a view name, the corresponding view will be the name of the action. So:
public ActionResult MethodA()
{
return View();
}
will render ~/Views/ControllerName/MethodA.cshtml.
But you could also specify a view name:
public ActionResult MethodA()
{
return View("FooBar");
}
and now the ~/Views/ControllerName/FooBar.cshtml view will be rendered.
Or you could even specify a fully qualified view name which is not inside the views folder of the current controller:
public ActionResult MethodA()
{
return View("~/Views/Foo/Baz.cshtml");
}
Now obviously all this assumes Razor as view engine. If you are using WebForms, replace .cshtml with .aspx or .ascx (if you are working with partials).
For example if there is no view it will even tell you where and in what order is looking for views:
Remember: ASP.NET MVC is all about convention over configuration.
The MVC framework use convention over configuration. The framework calls the ExecuteResult on the ViewResult object (created by the return View();). The framework by convention then looks in a number of locations to find a view
If you are using areas the framework will look in the following locations for a view.
/Areas//Views/ControllerName/ViewName.aspx
/Areas//Views/ControllerName/ViewName.ascx
/Areas//Views/Shared/ViewName.aspx
/Areas//Views/Shared/ViewName.ascx
/Areas//Views/ControllerName/ViewName.cshtml
/Areas//Views/ControllerName/ViewName.vbhtml
/Areas//Views/Shared/ViewName.cshtml
/Areas//Views/Shared/ViewName.vbhtml
Without areas (or if you are using areas and no view has been found) the framework will look at the following locations
/Views/ControllerName/ViewName.aspx
/Views/ControllerName/ViewName.ascx
/Views/Shared/ViewName.aspx
/Views/Shared/ViewName.ascx
/Views/ControllerName/ViewName.cshtml
/Views/ControllerName/ViewName.vbhtml
/Views/Shared/ViewName.cshtml
/Views/Shared/ViewName.vbhtml
As soon as the Framework tests a location and finds a file, then the search stops,
and the view that has been found is used to render the response to the client.
There are a number of overriden versions of the View method. The most common one is to render a specific view, outside of the framework convention, by calling it by name. For example
return View("~/Views/AnotherIndex.cshtml");
As an interesting footnote, the framework looks for legacy ASP, C# and VB Razor views (aspx, ascx, cshtml and vbhtml) even though you have a specific view engine.
In MVC controller action is not bound to view.
It uses delegate mechanism to pickup the view.
Model Binding(Mapping)
I was looking for the same and I just made a couple of tests and figured out.
It doesn't save anywhere.
To understand how it works; just do these steps:
In your controller, right click, Add View
Then enter a different View Name
and Ctrl F5
you will get Server error in application.
For example if you right click , Add View in following Index action method and type "Index2" in View name, you will get the error.
public class TestController : Controller
{
// GET: Test
public ActionResult Index()
{
return View();
}
}
So basically there is a 1-1 matching between action name and View name. And you cannot add view for the same method so there is no need to save in a config file.
Now change the view file name in Visual Studio from Index2.cshtml to Index.cshtml then Ctrl+F5. You should see it is working.
I am trying to build a functionality where I need to a create a candidate's profile in our application. There are two steps/UI's to create a candidate's profile:
1 - Create template...where the user enters candidate's information.
2 - Preview template...where the user will be shown a preview of how their profile would look like once they add the profile to our system.
I have already created the views to support these UI's via a controller called "CandidateController" which contains few action methods:
1- [HttpGet] "Create" that returns a Create template.
[HttpGet]
public ViewResult Create()
2- [HttpPost] "Preview" that returns a Preview template.
[HttpPost]
public ActionResult Preview(ProfileViewModel viewModel)
Now what I need to implement is to have a button/link in the Create template that would call the action method [HttpPost] Preview in the controller.
Challenge
I am also wondering if there is a way that the model binder would load the ViewModel object for me if am able to call the HttpPost Preview action method from the first create template.
I am looking for a suggestion/help to how to best achieve this kind a functionality.
Any help will be deeply appreciated.
Challenge I am also wondering if there is a way that the model binder
would load the ViewModel object for me if am able to call the HttpPost
Preview action method from the first create template.
You could use either a standard form or an AJAX call to invoke the Preview POST action and pass all the property values of the view model then. All the values you pass in this request will be the values that will be bound by the default model binder. Here's an article explaining how the default model binder expects the parameters to be named for more complex structure such as lists and dictionaries.
Example with AJAX:
$.ajax({
url: '#Url.Action("Preview")',
type: 'POST',
data: { Prop1: 'value 1', Prop2: 'value 2' },
success: function(result) {
// TODO: do something with the result returned from the POST action
}
});
If you don't want to use AJAX you could use a standard form with hidden fields:
#using (Html.BeginForm())
{
#Html.Hidden("Prop1", "value 1")
#Html.Hidden("Prop2", "value 2")
...
<button type="submit">Preview</button>
}
OK so here are the options that I had to get around:
As Darin suggested you may go with the unobtrusive way by using $.ajax(options), however the thing is you might want to go this way only if you want to do a partial page update or if you want to work on updating/dumping new html in the same view.
And if you don't want to use the Ajax, instead of using Hidden fields, you can simply use the TempData property in MVC, this is how I implemented my targeted functionality using TempData. p.s.below...
[HttpPost]
public ActionResult Create(ViewModel viewModel)
{
this.TempData["profile"] = viewModel;
return RedirectToAction("Preview");
}
public ActionResult Preview()
{
if (TempData["profile"] != null)
{
return View((ViewModel)TempData["profile"]);
}
// Handle invalid request...
return null;
}
So, this solution worked pretty well for me, where I did not write any JavaScript or unnecessary HTML. AND thanks Darin for directing me to a starting point.