ASP.NET MVC render partial from the POST method - asp.net-mvc

Problem
I have Telerik TabControl and each tab content is a partial view. Everything works smoothly when request is GET:
//
// GET: /ProductVersion/Translations
public ActionResult Translations(Guid id)
{
VersionEditTabViewModel model = CreateTranslationsViewModel(id);
return PartialView("Translations", model);
}
Now the problem is that on some tabs I have a Form that has controls that trigger submit event.
[HttpPost]
public ActionResult Translations(Guid id)
{
FormCollection formCollection = new FormCollection(Request.Form);
string message = string.Empty;
int languageId = int.Parse(formCollection["TranslationsLanguageList"]);
string action = formCollection["TranslationAction"];
if(action == Constants.translation_save)
{
_translationModel.SaveTranslations(formCollection);
message = "Translation information saved";
}
else if (action == Constants.translation_language_changed)
{
/*
PROBLEM: causes whole page to render, not partial
*/
return PartialView("Translations", model);
}
return RedirectToAction( ... updates the complete page not only partial ...);
}
My question is: how to render partial from the POST method? Because now with that source code tab content will be loaded to the WHOLE page, not inside tab.
Solution
I had to put DIV outside of the Ajax.Form and also I had incorrect submit on my DropDownList. What I did was that I created hidden submit button with Id and then I used jQuery to execute it's click event.

For additional reference, please refer to this question on SO:
MVC - Using Ajax to render partial view
This shows a complete implementation of the Ajax.BeginForm with surrounding DIV and inner form controls. You should be able to place this entire setup (DIV + Form + HTML Form Elements) in the Telerik Tab, like this:
<% Html.Telerik().TabStrip()
.Name("TabStrip")
.Items(tabstrip =>
{
tabstrip.Add()
.Text("Your Tab Text")
.Content(() =>
{%>
<div id="containerDiv" align="left">
<% using (Ajax.BeginForm("Example", "Controller/Action", new AjaxOptions { UpdateTargetId = "containerDiv" })){ %>
<%-- Render Partial here -->
<% } %>
</div>
<%});
Hope that helps.

I did my trough ajax form:
using (Ajax.BeginForm("*ActionName*", new { *parameter = ID* }, new AjaxOptions { UpdateTargetId = (*div i will update*), OnSuccess = "*JavaScript that executes on success*", OnComplete = "s*ame as on success*", InsertionMode = InsertionMode.Replace }))
and then i have
return PartialView("*PartialViewName*", model);
in post Action
And it works just fine, on post, action returns partial view and then ajax form replaces the content of the div specified in the UpdateTargetId with InsertionMode.Replace

Related

How can I save form data between pages asp.net mvc?

I have a long form that's been split up into separate pages using partial views. I want to save the data entered into one partial view form when the user clicks to go to the next patial view form. Then have it so that when they come back to the previous view then the data entered will be there.
So what i need is to post the data to a controller.
Although what I am using for the partial view is:
#Ajax.ActionLink("Job Information", "JobInformation", new AjaxOptions { InsertionMode = InsertionMode.Replace, UpdateTargetId = "jobForm"})
When they click the action link it takes them to the next page (partial view)
So how can i submit the form when they click the action link?
how can i submit the form when they click the action link?
i need is to post the data to a controller.
Instead of using AJAX ActionLink use AJAX BeginForm as shown below. Lets say you have a model like below, to populate a dropdownlist.
public class DDLModel
{
public List<SelectListItem> Items { get; set; }
public string SelectedValue { get; set; }
}
Then you have controller to display this model -
#model MVC.Controllers.DDLModel
#{
ViewBag.Title = "Index";
}
<h2>Index</h2>
<script src="~/Scripts/jquery-1.10.2.min.js"></script>
<script src="~/Scripts/jquery.unobtrusive-ajax.min.js"></script>
#using (Ajax.BeginForm("Submit", "Ajax", new AjaxOptions { UpdateTargetId = "SellerWebSettings" }, new { id = "form1" }))
{
#Html.DropDownListFor(m => m.SelectedValue, Model.Items, "DDL")
<input type="submit" value="Click" />
}
<div id="SellerWebSettings">
</div>
In the above form, you have a AJAX BeginForm() which would make a AJAX all to another controller action which will return a PartialView. The model will also be forwarded to the partial view, as shown below -
public ActionResult Submit(DDLModel model)
{
return PartialView("MyPartial",model);
}
And the partial view is as follows -
#model MVC.Controllers.DDLModel
<div>
#DateTime.Now - #Model.SelectedValue
</div>
So when we select the Dropdownlist item and click on the button, we have following output -

ViewData not shown in Ajax.BeginForm

I have creatd a partial view and inside it I am using AJAx.BeginForm. In Post Edit Action Method, I am adding VIEWDATA Like this
if (ModelState.IsValid)
{
service.SaveAccount(account);
TempData["message"] = "Account has been updated successfully!";
AccountInfo accountInfo = new AccountInfo();
accountInfo.AccountStatuses = service.GetAccountStatuses();
accountInfo.AccountTypes = service.GetAccountTypes();
accountInfo.CreditTerms = service.GetCreditTerms();
return View("DisputeSubscriber", accountInfo);
}
else
{
return PartialView("_UpdateAccountDetails", account);
}
and redirecting to same partial view. In partial view, I have added like this:
#if (TempData["message"] != null)
{
<div class="Message">
I am here.
#TempData["message"]
</div>
}
but this message is not shows. this message is also inside AJAX.BeginForm. Please suggest
Do I need to redirect main view instead of partial view or there is something I am missing
You seem to be using TempData and not ViewData which is not quite the same. Also you mentioned that you are using an Ajax.BeginForm to invoke this controller action. Since this is an AJAX call make sure that you have specified an UpdateTargetId in your AjaxOptions so that the resulting partial is injected somewhere into the DOM:
#using (Html.BeginForm(new AjaxOptions { UpdateTargetId = "foo" }))
{
...
}
<div id="foo"></div>

MVC 3 StackOverflowException w/ #Html.Action()

I've looked over a bunch of other reports of this, but mine seems to be behaving a bit differently. I am returning PartialViewResults for my child actions, so that's not the source of the recursion. Here's a dumbed down version of what I have.
// The Controller
[ChildActionOnly]
public ActionResult _EditBillingInfo()
{
// Generate model
return PartialView(model);
}
[HttpPost]
public ActionResult _EditBillingInfo(EditBillingInfoViewModel model)
{
// Update billing informatoin
var profileModel = new EditProfileViewModel()
{
PartialToLoad = "_EditBillingInfo"
};
return View("EditProfile", profileModel);
}
[ChildActionOnly]
public ActionResult _EditUserInfo()
{
// Generate model
return PartialView(model);
}
[HttpPost]
public ActionResult _EditUserInfo(EditUserInfoViewModel model)
{
// Update user informatoin
var profileModel = new EditProfileViewModel()
{
PartialToLoad = "_EditUserInfo"
};
return View("EditProfile", profileModel);
}
public ActionResult EditProfile(EditProfileViewModel model)
{
if (String.IsNullOrEmpty(model.PartialToLoad))
{
model.PartialToLoad = "_EditUserInfo";
}
return View(model);
}
// EditProfile View
#model UPLEX.Web.ViewModels.EditProfileViewModel
#{
ViewBag.Title = "Edit Profile";
Layout = "~/Views/Shared/_LoggedInLayout.cshtml";
}
<div>
<h2>Edit Profile</h2>
<ul>
<li class="up one"><span>#Ajax.ActionLink("Account Information", "_EditUserInfo",
new AjaxOptions { UpdateTargetId = "EditProfileDiv", LoadingElementId = "LoadingImage" })</span></li>
<li class="up two"><span>#Ajax.ActionLink("Billing Information", "_EditBillingInfo",
new AjaxOptions { UpdateTargetId = "EditProfileDiv", LoadingElementId = "LoadingImage" })</span></li>
</ul>
<img alt="Loading Image" id="LoadingImage" style="display: none;" src="../../Content/Images/Misc/ajax-loader.gif" />
<div id="EditProfileDiv">
#Html.Action(Model.PartialToLoad)
</div>
</div>
The partial views are both forms for updating either the user information or billing information.
I debugged through this and found what is happening, but cannot figure out why. When a user browses to EditProfile, it load up with the _EditUserInfo partial and the form is there for editing. When you change some info and submit the form it hangs and you get a StackOverflowException in the EditProfile view on the call to #Html.Action(). What happens is on the initial visit to EditProfile, the #Html.Action calls the HttpGet version of _EditUserInfo. You make some changes to the user info and click submit. Once the information is updated the EditProfile view is returned again, but this time #Html.Action calls the HttpPost version of _EditUserInfo which updates the user information again, returns the EditProfile view again and the #Html.Action calls the HttpPost version of _EditUserInfo... You get where this is going. Why after form submission does it call the post version and not the get version like it did for the initial visit to EditProfile?
Thanks for any help!
I might be getting this a bit wrong, it's been a long day so, but in EditProfile you set PartialToLoad (if it's empty) to "_EditUserInfo", then in _EditUserInfo you set it again to _EditUserInfo, won't this create a loop that behaves as what you are experiencing?

how to render a full view using Ajax.BeginForm

I have a partial view which has a Ajax.BeginForm, with a UpdateTargetID set. When the validation on the form fails the update target id is replaced with the validation errors, but when there are no validation errors users should be redirected to a new page.
The code in my Partial view is
<div id="div_UID">
<% using (Ajax.BeginForm("FindChildByUID", new AjaxOptions { UpdateTargetId = "div_UID" } ))
{%>
<p>
<label>UID:</label>
<%= Html.TextBox("UID") %>
</p>
<input type="submit" value="Continue" />
<% } %>
</div>
</pre>
The code in my controller is as follows
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult FindChildByUID(Student student)
{
Student matchingStudent = _studentService.FindChildByUID(student.UID);
if (matchingStudent == null)
{
ModelState.AddModelError("UID", String.Format("No matching child found for the entered UID: {0}", student.UID));
return PartialView();
}
else
{
// full view
return RedirectToAction("ConfirmChildDetails", matchingStudent);
}
}
So, for I have been unsuccessful to display the full view on it's own, as it always seems to dipslay the full view in the UpdateTargetID div specfied in the Ajax.BeginForm.
Any suggestions on how I can get this to work?
Thanks
What your AJAX post is doing is making a request and waiting on a response that contains html to input onto the page. The configuration is such that whatever html is returned will be injected into the div you've named "div_UID".
I typically avoid scenarios like this and use traditional posting if a redirect is required upon a successful outcome of the POST.
I imagine you could do it like this using jQuery to submit rather than the Ajax.BeginForm (or just set a callback function for your Ajax.BeginForm):
function SubmitForm(form) {
$(form).ajaxSubmit({ target: "#div_to_update", success: CheckValidity });
}
function CheckValidity(responseText) {
var value = $("#did_process_succeed").val();
if (value == "True") {
window.location.replace("url_of_new_action_here");
}
}
You just have to have a hidden field in your partial view called "did_process_succeed" and set the value of True or False based on some logic in your controller.
There are likely other ways as well. Perhaps someone else will chime in. I hope this helps for now.

asp.net mvc ajax.BeginForm Redirecting

I dont think i quite get the Ajax functions in mvc, because i get this wierd problem.
I got the following code which makes my ajax call, it is placed in a partial view with a productList:
<% using(Ajax.BeginForm("AddToBasket", "Basket",
new { productID = item.Id },
new AjaxOptions { HttpMethod = "Post", UpdateTargetId = "Basket", OnSuccess = "productAdded(" + item.Id + ")" })) { %>
<input type="image" src="/Content/addToCart.png" />
<% } %>
I have a <div id="Basket"></div> on my masterpage
And this method in BasketController, which returns a partial view that is found in Basket/BasketList.ascx:
[HttpPost]
public ActionResult AddToBasket(int productID)
{
// DO STUFF
return PartialView("BasketList");
}
When i am logged in using the default asp.net membership it all works fine, it updates the basket and it is all async, but when i am logged out and is clicking the addToCart, it redirects me to Basket/AddToBasket?productID=1, which is a partial view.
Does anyone know why this happens?
I have a similar problem with an ajax.actionlink
<%= Ajax.ActionLink("Gem", "SaveBasket", "Basket", new AjaxOptions { HttpMethod = "Post" })%>
where it says "The resource cannot be found." when it should fire, which is placed in the BasketController
[HttpPost]
public void SaveBasket()
{
// DO STUFF
}
It sounds like you have a javascript error somewhere that is blocking the AJAX stuff that should be happening. Can't say why that would only happen when logged out though.
Do you have any errors in the error console/firebug?
Are you sure all your pages are including the Microsoft Ajax libraries? And in the correct order?

Resources