ASP.NET MVC: View gets rendered in an alert window - c#

My view gets rendered in an alert window. I have a post action that adds a new record to my repository, and then returns a list of matching objects for display:
[HttpPost]
public ActionResult Add(FormCollection collection)
{
...
_repository.AddMyObject(myobject);
_repository.Save()
_matchingResults = _repository.GetMatchingResults(myobject);
if (Request.IsAjaxRequest())
return View("Results", _matchingResults );
...
}
"Results" is a view that renders a list of matchingResults. However, all I get is an alert window with the rendered html. I can't use RedirectToAction because I need to pass in _matchingResults.
Any suggestions?

Your view rendering the results should be a partial view i.e. Results.ascx (user control) and then you would return that to the view via return PartialView("Results", _matchingResults)

One work around although ugly might be to use Tempdata to store what you want and retrieve it in your Results action as TempData persists between two requests
However TempData can only store strings but Phil Haacked comes to a rescue with this blog.
A common pattern when submitting a
form in ASP.NET MVC is to post the
form data to an action which performs
some operation and then redirects to
another action afterwards. The only
problem is, the form data is not
repopulated automatically after a
redirect. Let's look at remedying
that, shall we?

Related

Return to the same view after asp-action

This is about an MVC WebApp (that also uses EF). My question is about returning to the same view after an asp-action.
I display a list of users (db records on my .cshtml page). Next to each user, I have a Reset Password hyperlink. Upon clicking the hyperlink, I use EF to reset the user's password. This is done through an asp-action
<a asp-action="ResetPassword" asp-route-userid="#item.userid">Reset Password</a>
This reset asp-action is all happening fine.
But post asp-action, I would like to return back to the same view (from where I originally clicked the Reset Password hyperlink).
I do not need any refreshes or re-launch of the view. I find examples in StackOverflow about using Ajax if its a form/submit button action. In my case there's no submit button action or form or another view being shown.
Any suggestions on how to return back to the same View?
In your controller ResetPassword method, you can redirect to the action that initially displayed your view. You don't have your controller or view names listed in your question, so I'll make some guesses here:
public class UsersController : Controller
{
public ActionResult Index()
{
//get user data/setup model (or do it from the view via ajax)
return View(model);
}
public ActionResult ResetPassword(int id)
{
//do reset password work
//return redirect to the Index page that lists your user data
return RedirectToAction("Index", "Users");
}
}
Now, while the above will work, it would be a better experience for the user (and lower server/db impact) if the call to ResetPassword was done via ajax, since a full page refresh wouldn't be needed.

how to pass data from one view to another

I want to pass object data from one view to another on click of button.
I am calling the action to load the second view via ajax.
In the controller action I am trying to pass object data to view. But the view is not rendered.
How can I achieve the scenario of passing data from one view and populating it to the controls of other view?
I want to pass object data from one view to another on click of button
When in any Action or ActionResult you have
return RedirectToAction("controllerName","viewname","parameters")
so the Action Method instead of returning a view, this will redirect to another view Action method and that view will be rendered.
You need to send the data from one view to another in form of query string or post parameters to an action.
Ex:
[HttpPost]
public ActionResult PassData(string dataFromView1)
{
return View("View2", dataFromView1);
}
Note: Here i used a single string data in a parameter. If your View1 has more data/complex data structure, better to use ViewModel class and pass that to your intermediate controller.
I want to pass object data from one view to another on click of button
You need to pass View in HttpPost method. Look at this code.
[HttpPost]
public ActionResult YourActionName(Model model)
{
return View("AnotherActionName", model);
}
Or you can use RedirectToAction.

Controller that calls a partial view that should display inside the Layout view

In a standard MVC application we have _Layout.cshtml and an Index.cshtml view. Now imagine if the user receives an email activation after a registration and now he/she clicks on that link.
The link points to /Account/ActivateAccount and after I process the activation, I wanted to redirect the user to the Login.cshtml partial view displaying a message.
I'm aware I can pass the message via the TempData["Message"] but what I don't know is how to redirect to a partial view and have that display inside the _Layout.cshtml instead that by itself.
At least this is what is happening when I call RedirectToAction("Login", "Home")
Note: all "home" based partial views are displaying within a < div id="divmain"> and my ideal solution would be to be able to decide what view should display inside that div, from the controller.
What's the right way to call a Partial View to be displayed from within another Controller ??
I'm not entirely sure I understand the question but I think what you're asking is if you can call a partial view from the _layout? This can be done with #Html.Action() helper. It will call out to a controller and method you specify and insert the result. The method you call would just be a PartialResult that returns the partial view with whatever data you need.
This is in contrast to #Html.Partial() which will render the partial view in place with whatever data you provide without routing back through a controller.
EDIT:
To summarize the comments to this answer, it seems I misunderstood the requirement. A user receives an email and clicks the link to activate their registration. The controller action that handles that request activates the user and then it needs to redirect to something. In this case, there was already a partial view which would serve the purpose but it couldn't be redirected to directly for some reasons. My suggestion was to just create a new View which contained a #Html.Partial() call to basically wrap the partial in a full view page.
The action method which handled the click could then just return that view directly or, if you consider the click of the link to be a "post" since it changes the application model by validating the user, you would create a new controller action and return RedirectToAction() directly. This would be like following the Post, Redirect, Get method and would prevent some issue if the user tried to refresh the "activated" page. It would also give more control over the URL naming.

Is using tempdata validate method entry and pass info through multiple POSTs in the controller a bad practice? Alternatives?

First, some context:
In my controllers, I return RedirectToAction's on successful HTTP POSTs. I use TempData to hold onto the user's entered model data so that the method I redirect to can use this input data again.
Example:
1. Enter userID into search field.
2. Click button, POST is performed, user is found in database through my repository, userID stored in TempData, call RedirectToAction("Edit")
TempData["user"] = searchViewModel.userID;
return RedirectToAction("Edit");
perform edits on Edit view, click commit button, user info is stored in TempData, call RedirectToAction("Confirm");
display changes made on the Confirm view, click "Confirm", final HTTP POST is performed and changes are made through my repository service.
This seems to work well. In order to handle people trying to skip ahead to a page in the address bar by typing "../Edit/Confirm" I have this check in my Confirm method:
if (TempData["editUserViewModel"] == null)
return RedirectToActionPermanent("Edit");
Is this the best way to handle address bar input? I also do TempData.Keep("editUserViewModel") so that refreshes work. Is this the best way to handle refreshes?
For going from step 1 to 2, I would suggest a paramaterized action instead:
Enter userID into search field.
Click button, POST is performed, user is found in database through my repository
Call RedirectToAction("Edit", new {UserId = foundUserId})
Also, when searching, you probably shouldn't be doing a POST. A GET is just fine when you are looking for information and not mutating it. This avoids the PRG pattern altogether for the first place where you are using tempdata, since you do a GET instead of a POST.
As for the confirm, there is another way to do this without tempdata. Instead of redirecting to your Confirm action, POST to it, and return your confirm viewmodel. Only after that second POST do you hit the repos and finish out the PRG pattern after the POST with a Redirect and finally a Get.
Users should not be able to do any type of GET for your Confirm action, as can be seen by your bandaid for it. So, just don't allow gets at all. POST from the edit form to the confirm action, return a view, and then POST from that view to a second POST action method. Since these are all part of the same process, you shouldn't have to deal with redirects or tempdata until the process is complete (repos updated).
Update (reply to comments)
1.) If I remove the [HttpPost] attribute on my SearchUser function, how will my search button on the view know what to call?
Your search button is nested within a <form> HTML element. You will need to change the form's method to GET. If the attribute is not present, I believe POST is the default. Your search button will remain the same, but the form will submit the user-enetered input as an HTTP GET request instead of an HTTP POST:
<form method="GET">
...
<input type="submit" value="Search" />
</form>
2.) Can you clarify removing the Redirect to Confirm? I'm having trouble understanding how I would change a Redirect to a POST
It's difficult to explain this to someone just starting with web development, but in essence, every redirect is always an HTTP GET request. This is why you had to put the data into session (tempdata uses session) in order to maintain it across stateless requests.
Basically, here is your workflow:
User enters search input and clicks submit
The search in (1) is sent as a GET request to some action method, which returns a view.
The view returned in (2) contains a <form method="POST" action="/Users/StillNeedsConfirmationAction"> with additional input elements. This is the form that will be used to edit data.
User inputs data in the form view from (3) and clicks submit.
The action method StillNeedsConfirmationAction on your UsersController accepts an HTTP POST with a viewmodel object. Rather than redirecting though, the action simply returns another view, passing the same viewmodel object.
The view returned in (5) contains a <form method="POST" action="/Users/ConfirmAndUpdateAction">. It will render hidden inputs for each text box or other form element in your previous POST form.
User clicks submit on the second form to confirm fields
The action method ConfirmAndUpdateAction on your UsersController accepts an HTTP POST with the same viewmodel object that your other POST action did. However instead of returning another view, this time it saves the data in your repository and redirects.

popup from asp.net mvc controller

how can i show an popup coming from a controller after my task has finished? something like to notice the user it has been finished?
You have to return an ActionResult from the controller action that can be rendered by the browser. That's usually either a whole page, or a partial page or JSON data returned to an Ajax call. The javascript in the page can then display the result returned.
I resolved this as following:
step 1- create a partial view name "_Empty.cshtml"
then, in that view you can send message to end user based on your controller condition.
and in the controller write this two lines:
ViewData["AlertMessage"] = AlertMessage.NoClient;
return PartialView("_Empty");
here the user not select any client, so i redirect user to empty partial view and tell user that please select client then proceed to another opration.

Categories