Here's my View (Model ActivityViewModel):
#model GPMS.Models.ActivityViewModel
<div class="tab-pane" id="managepayments" role="tabpanel">
#{ Html.RenderPartial("_Payments", Model.Payments); }
</div>
Which render a Partial (Model IEnumerable<GPMS.Models.PaymentViewModel>):
#model IEnumerable<GPMS.Models.PaymentViewModel>
#using (Ajax.BeginForm("SavePayments", "Activities", new AjaxOptions { HttpMethod = "POST", UpdateTargetId = "DynamicContainer", InsertionMode = InsertionMode.Replace, OnBegin = "AjaxBeginFormOnBegin", OnComplete = "AjaxBeginFormOnComplete", OnSuccess = "AjaxBeginFormOnSuccess", OnFailure = "AjaxBeginFormOnFailure" }))
{
#Html.AntiForgeryToken()
<!-- My Form -->
}
Which send Ajax request to my Controller's Action:
public ActionResult SavePayments(IEnumerable<PaymentViewModel> payments)
{
if (ModelState.IsValid) {
// code; here I need ActivityViewModel.ID
}
}
The question is: how can I pass to that SavePayments also my activity ID stored in ActivityViewModel.ID? Can I do with routing?
I don't want to pass the whole ActivityViewModel to SavePayments, otherwise I need to take care of its required fields for the ModelState.IsValid check.
One option is to use the overload of Html.Partial to pass the ID using additionalViewData, then retrieve it in the partial view and add it as a route value in the form.
In the main view
#{ Html.RenderPartial("_Payments", Model.Payments, new ViewDataDictionary { { "ID", Model.ID} }); }
And in the partial
#using (Ajax.BeginForm("SavePayments", "Activities", new { id = ViewData["ID"] }, new AjaxOptions { ....
Then add a parameter in the POST method for the ID
public ActionResult SavePayments(int id, IEnumerable<PaymentViewModel> payments)
Related
I'm making a post request from on view so that I don't see the parameters on the URL and I can tell it is passing the appropriate parameters to controller for the request but it does not display the appropriate view from that controller.
Calling view
#Ajax.ActionLink("Work1", "NewIndex", "WorkItems",
new
{
eventCommand = "createforrig",
//eventArgument1 = #item.Id,
eventArgument2 = #item.Id
},
new AjaxOptions
{
HttpMethod = "POST"
})
WorkItems Controller method
[HttpPost]
public ActionResult NewIndex(NewWorkItemViewModel vm)
{
vm.IsValid = ModelState.IsValid;
vm.HandleRequest();
if (vm.IsValid)
{
// NOTE: Must clear the model state in order to bind
// the #Html helpers to the new model values
ModelState.Clear();
}
else
{
foreach (KeyValuePair<string, string> item in vm.ValidationErrors)
{
ModelState.AddModelError(item.Key, item.Value);
}
}
return View(vm);
}
Putting a breakpoint on the last Return View(vm) confirms it is being called but the browsers does not update to display the workItems view.
Suggestions on why the browser is not being updated to display the appropriate view.
You're making an ajax post, the newly rendered view is being returned by the server if you were to look in the network console in your browser. Add a success callback. Either assign a callback to handle the response or use the
UpdateTargetId property in your AjaxOptions
#Ajax.ActionLink("Work1", "NewIndex", "WorkItems",
new
{
eventCommand = "createforrig",
//eventArgument1 = #item.Id,
eventArgument2 = #item.Id
},
new AjaxOptions
{
HttpMethod = "POST",
OnSuccess = "AjaxSuccess", //handle with callback
UpdateTargetId = "MyElementID" //update html element
})
if you choose to use OnSuccess then in javascript
function AjaxSuccess(data){
//handle response
}
AjaxOptions properties and usage can be found here
EDIT
You could use javascript to submit a form when a link is clicked, put a form somewhere in your code and hide it.
#using (Html.BeginForm("NewIndex", "WorkItems", FormMethod.Post,
new { class = "hidden", id = "postForm" } ))
{
<input type="hidden" name="eventCommand" value="createforrig" />
<input type="hidden" name="eventArgument2" value="#item.Id" />
<input type="submit" value="link text" id="submitForm"/>
}
then change your #Ajax.ActionLink... to
#Html.ActionLink("Work1", "NewIndex", "WorkItems", new { id = "postLink"})
and if you're using jQuery
<script>
$(function(){
$('#postLink').click(function(e)
{
e.preventDefault();
$('#postForm').submit();
});
});
</script>
and don't forget to hide the form in css
.hidden { display:none;}
This is my link to a partial view:
#Ajax.ActionLink("All", "All", "Products", new { id = Model.id_product }, new AjaxOptions()
{
HttpMethod = "GET",
UpdateTargetId = "divImages",
InsertionMode = InsertionMode.Replace
})
<div id="divImages"></div>
and here's the method being invoked and returns the partial view:
public PartialViewResult All(int id)
{
List<Image> model = db.Images.Where(x => x.id_product == id).ToList();
return PartialView("_File", model);
}
I want my partial view to be loaded immediately after the main view loaded instead of the link to the partial view. How can I do that?
To render a partial view generated by a controller method in the main view, use #Html.Action() or #{ Html.RenderAction(); }
#{ Html.RenderAction("All", "Products", new { id = Model.id_product }); }
Main view contains #Ajax.ActionLink links that updates a div target with partialViews. All works fine.
#Ajax.ActionLink("Update", "MemberInfo", new AjaxOptions() { HttpMethod = "GET", UpdateTargetId = "divCurrentView", InsertionMode = InsertionMode.Replace })
<div id="divCurrentView"></div>
Question is: When displaying a partialview and on click currently I update data and return to the same partial view that reloads the data. also reloads dropdownlists..etc `
Calling Partial View:
public PartialViewResult MemberInfo(){
.......
ViewBag.Members= new SelectList(_db.Members, "Id", "Text");
return PartialView("_MemberInfo",model);
}
[HttpPost]
public PartialViewResult MemberInfo(InformationVM model){
....... update data
//if I dont include the ViewBag again it will fail on reload
ViewBag.Members= new SelectList(_db.Members, "Id", "Text");
return PartialView("_MemberInfo",model);
}
instead of return to the same PartialView can I just show a message on the screen "data was updated" within the partial view.?
When you define your ActionLink, you can choose the element that gets replaced:
#Ajax.ActionLink("Do something", "_Methodname", new AjaxOptions {
HttpMethod = "POST",
UpdateTargetId = "StatusMessage",
InsertionMode = InsertionMode.Replace,
}, new {#class = "text-danger"})
<span id="StatusMessage"></span>
This way, the message gets loaded into the span element.
In that case, I'd include the actionlink inside the div and replace the content of the div (including the actionlink) with the partial, this time including another (different) actionlink.
<div id="divCurrentView">
#Ajax.ActionLink("Update", "MemberInfo", new AjaxOptions() { HttpMethod = "GET", UpdateTargetId = "divCurrentView", InsertionMode = InsertionMode.Replace })
</div>
Partial:
<div id="divCurrentView">
#Ajax.ActionLink("Update", "MemberInfo", new AjaxOptions {
HttpMethod = "POST", UpdateTargetId = "StatusMessage", InsertionMode = InsertionMode.Replace})
<span id="StatusMessage"></span>
</div>
That way, the second (and subsequent) clicks will POST and use the different method in the controller.
Still trying to figure that out, here is my workflow:
once submit been clicked, the jquery will send a post request to call the method
method return a partial view
display on <div id = "messageForm">...</div> part
below is the form view:
//SignUp.cshtml:
<div id ="messageForm">
#using (Ajax.BeginForm("SignUp", "MVP", new AjaxOptions
{
Confirm = "Are you sure you want to send this message?",
HttpMethod = "Post",
InsertionMode = InsertionMode.Replace,
LoadingElementId = "loading",
UpdateTargetId = "messageForm"
})) {
#Html.AntiForgeryToken();
#Html.ValidationSummary(true)
<fieldset>
<legend>
messageModel
</legend>
<p>
<input type ="submit" value ="Send Message" />
</p>
</fieldset>
here is the controller:
//MVPController
[HttpPost]
public ActionResult SignUp(MVCView model){
return PartialView("_ThankYou");
}
public ActionResult SignUp(){
return View();
}
Here is the partial view in view folder:
ThankYou.cshtml:
<h1>Thank you so much! We will contact you later</h1>
When testing it, I didn't see the confirm dialog and it redirect to the thank you page
Can anyone tell me why that happened?
You have:
#using (Ajax.BeginForm("ThankYou", "MVP", new AjaxOptions
I think this should be:
#using (Ajax.BeginForm("SignUp", "MVP", new AjaxOptions
The first string is the Action name, and you only have SignUp in the controller.
When I'm clicking ActionLink and setting ViewModel values in controller I can see changes when View being rendered. But same values comes as null into Controller when I'm clicking ActionLink second time.
How do I store the value, so it comes into controller ?
View:
#Ajax.ActionLink("Click me", "AjaxTest", "Controller", new AjaxOptions()
{
UpdateTargetId = "updatePanel",
HttpMethod = "POST",
OnSuccess = "A()"
})
<div id="updatePanel">
#Html.Partial("~/Views/Shared/_UpdatableContent.cshtml", this.Model)
</div>
Controller:
[HttpPost]
public ActionResult AjaxTest(MyViewModel model)
{
model.A = "A"
return PartialView("_UpdatableContent", model);
}
Partial view _UpdatableContent:
#Html.HiddenFor(x => x.A)
#if (Model.A == "A")
{
//Draw
}
Try adding this.Model to your ActionLink following:
#Ajax.ActionLink("Click me", "AjaxTest", "Controller", this.Model, new AjaxOptions() { UpdateTargetId = "updatePanel" })
This method passes the model back into the request, which should allow the update to happen.
Probably my biggest gripe with ASP.NET MVC is the fact that the various "Helper" functions are overloaded to the nth-degree, and not always consistently in terms of the order the arguments appear...
Hope that helps :)
I had this very same problem. Setting HttpMethod = "Post" in the AjaxOptions fixed it for me, thanks Sergejs.
My final, working code is as follows
#{
AjaxOptions ajaxOptions = new AjaxOptions
{
HttpMethod = "Post",
LoadingElementId = "product-adding-" +#Model.Product.Id,
LoadingElementDuration = 100,
OnSuccess = "AddedToCart"
};
}
<div>
#Ajax.ActionLink("Add to cart",
"AddToCart",
"Cart",
new { id = Model.Product.Id, returnUrl = Request.Url.PathAndQuery },
ajaxOptions,
new { #class = "button" })
<img id="product-adding-#Model.Product.Id" src="~/Images/ajax_loader.gif" />
</div>