Multiple submits to different MVC controller actions from buttons or dropdownlist changes - asp.net-mvc

If I have a single form - with two submits:
From a save button - calls a form POST "Save" controller action.
From a change of a dropdown list value - calls a form POST "NoSave" controller action that returns a modified view without saving.
What's the best way of achieving this?
At the moment, I have the following - but they both call the same POST controller action. I want to call a named action for the dropdownlist update.
<form form method="POST">
<!-- dropdown list -->
<div class="row">
#Html.LabelFor(x => x.FieldName, "Field Name:")
#Html.DropDownListFor(x => x.FieldName, Model.FieldName, new { #class = "browser-default", #onchange = #"form.submit();" })
#Html.ValidationMessageFor(x => x.FieldName)
</div>
</div>
<!-- save button-->
<div class="save-button">
<input type="submit" class="btn" value="Save" />
</div>
</form>

what about using ajax request for different type of requests every type of request call different action or even different controller
[HttpPost]
public ActionResult SomeFunction(string a)
{
return Json("some data here", JsonRequestBehavior.AllowGet);
}
[HttpPost]
public ActionResult AnotherSomeFunction(string a)
{
return Json("some data here", JsonRequestBehavior.AllowGet);
}
//by click button
$("some button name ").click(function(){
$.ajax({
url: 'home/FirstAjax',
success: function(responce){ alert(responce.data)},
error: function(responce){ alert(responce.data)}
});
});
//by click another button
$("some button name ").click(function(){
$.ajax({
url: 'home/SecoundFirstAjax',
success: function(responce){ alert(responce.data)},
error: function(responce){ alert(responce.data)}
});
});

For this you can use ajax.beginform in first parameter you have to give the name of action and then controller and then some option which are like method type and success and failure actions.
#using (Ajax.BeginForm("_LoadPartial", "Abss", new AjaxOptions { HttpMethod = "POST", OnSuccess = "OnSuccess", OnFailure = "OnFailure" }))
{
<div class="row">
#Html.LabelFor(x => x.FieldName, "Field Name:")
#Html.DropDownListFor(x => x.FieldName, Model.FieldName, new { #class = "browser-default", #onchange = #"form.submit();" })
#Html.ValidationMessageFor(x => x.FieldName)
</div>
</div>
<!-- save button-->
<div class="save-button">
<input type="submit" class="btn" value="Save" />
</div>
}
Also provide OnSuccess and Failure Javascript fucntion on the same page.
<script>
function OnSuccess(){
// some action
}
function OnFailure(){
// some action
}
</script>

Related

Get changed item from DropDownListFor into another form

I have 3 forms each has access to its own Delete/Create/Edit action on server side.
When I change the DropDownListFor selected item and do a Delete then the string title is passed to the server
When I change the DropDownListFor selected item and do a Create/Edit then the string title is not passed to the server.
How can I let my Create/Edit form know of my change in the DropDownListFor ?
Passing the initial title value works with the Create/Edit action. So the problem is the change event.
index.cshtml
#using (Html.BeginForm(MVC.Configuration.Addresses.ActionNames.Delete, MVC.Configuration.Addresses.Name, new { #area = MVC.Configuration.Name }, FormMethod.Post, HtmlAttributes.Form))
{
<div class="form-group required">
#Html.LabelFor(m => m.Title, HtmlAttributes.Label)
<div class="col-md-6">
#(Html.Kendo().DropDownListFor(m => m.Title)
.BindTo(Model.Addresses.OrderBy(order => order.Text))
.HtmlAttributes(HtmlAttributes.KendoControl))
</div>
</div>
<input type="submit" value="Delete" class="btn btn-default" />
}
#using (Html.BeginForm(MVC.Configuration.Addresses.ActionNames.Edit, MVC.Configuration.Addresses.Name, new { #area = MVC.Configuration.Name }, FormMethod.Get, HtmlAttributes.Form))
{
#Html.HiddenFor(p => p.Title)
<input type="submit" value="Edit" class="btn btn-default" />
}
#using (Html.BeginForm(MVC.Configuration.Addresses.ActionNames.Add, MVC.Configuration.Addresses.Name, new { #area = MVC.Configuration.Name }, FormMethod.Get, HtmlAttributes.Form))
{
#Html.HiddenFor(p => p.Title)
<input type="submit" value="Add" class="btn btn-default" />
}
you can use 1 form with multiple buttons, you will achieve the desired result and your view will be cleaner.
As far as I know there are two main methods:
1 MVC Action: You can check the value of clicked submit button in MVC action and then perform the desired things. Example given that your buttons have as name "submitButtonName".
[HttpPost]
public ActionResult YourAction(string submitButtonName, YourFormModel model)
{
switch (submitButtonName) {
case "create":
CreateMethod(model);
break;
case "edit":
EditMethod(model);
break;
case "delete":
DeleteMethod(model);
break;
}
}
3 MVC Actions: You can change the form target action on button click using javascript. Example given that your buttons have as class "submitButtonClass".
$(".submitButtonClass").on("click", function(e){
e.preventDefault();
$('#yourFormId').attr('action', $(this).val()).submit();
});
I wrote the code quickly without testing it but it should work :)
Have a nice day,
Alberto

JQuery AJAX: Update ViewModel

I have a strongly-typed MVC view that includes a form with an editor that is bound to a view model:
#model ViewModels.CommentView
#using (Ajax.BeginForm("UpdateComments", new AjaxOptions { HttpMethod="POST" }))
{
<fieldset>
<legend>Metadata</legend>
<div>
#Html.HiddenFor(model => model.Id)
<div class="editor-label">
#Html.LabelFor(model => model.Comment)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Comment)
#Html.ValidationMessageFor(model => model.Comment)
</div>
</div>
<p class="action clear">
<input type="submit" value="Save" />
</p>
</fieldset>
}
When the user clicks on an element in a different part of the view, a JQuery AJAX call retrieves data from the server and updates the control:
<script type="text/javascript">
$(".load-comments").focus(function () {
var Id = $("#Id").val();
var url = "#Url.Action("GetComment")/" + Id;
$.ajax({ url: url, success: DataRetrieved, type: 'POST', dataType: 'json' });
function DataRetrieved(data) {
if (data) {
$("#Comment").val(data.Comment);
}
};
});
</script>
This functionality works as expected: the control content is visually updated. However, the value of the underlying html element is not updated, and when I post the form back to the server, the view model is empty.
How do I set the form controls' value in the JQuery function so that they post back to the server?
How did you set the HTML? ASP.NET default ModelBinder looks for id that are equals object properties to build the model back in the server. Looks like your form HTML doesnot reflect the object. Inspect each element created by Html helper and create each control as the same after comment data comes from the request. Hopes its help you! You can create a custom ModelBinder to Bind your model back in the server, take a look here: Model Biding

pass model from view to controller with html.actionlink

I am trying to get the model data from a strongly typed view to a controller.
Using the submit button is ok, I can get the data. Now I want to achieve the same with html.actionlink.
This is what I have:
View:
#model WordAutomation.Models.Document
#{
ViewBag.Title = "Document";
}
<script type="text/javascript">
$(function () {
$("#dialog").dialog();
});
</script>
<h2>Document</h2>
#using (Html.BeginForm()) {
#Html.ValidationSummary(true)
<fieldset>
<legend>Document</legend>
<div class="editor-label">
#Html.LabelFor(model => model.ClientTitle)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.ClientTitle)
#Html.ValidationMessageFor(model => model.ClientTitle)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.ClientFullName)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.ClientFullName)
#Html.ValidationMessageFor(model => model.ClientFullName)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.ClientCustomSSN)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.ClientCustomSSN)
#Html.ValidationMessageFor(model => model.ClientCustomSSN)
</div>
<p>
<input type="submit" value="Create" />
</p>
</fieldset>
}
<div>
#Html.ActionLink("Preview", "PreviewWordDocument", "Home", null, new { id = "previewLink" })
</div>
<div id="dialogcontainer">
<div id="dialogcontent"><input type="submit" value="Create" /> </div>
</div>
#section Scripts {
<script type="text/javascript">
$(document).ready(function() {
$("#dialogcontainer").dialog({
width: 400,
autoOpen:false,
resizable: false,
title: 'Test dialog',
open: function (event, ui) {
$("#dialogcontent").load("#Url.Action("PreviewWordDocument", "Home")");
},
buttons: {
"Close": function () {
$(this).dialog("close");
}
}
});
$("#previewLink").click(function(e) {
e.preventDefault();
$("#dialogcontainer").dialog('open');
});
});
</script>
}
Controller:
public ActionResult Document()
{
return View();
}
[HttpPost]
public ActionResult Document(WordAutomation.Models.Document model)
{
Models.Utility.EditWord word = new Models.Utility.EditWord();
word.EditWordDoc(model);
return View("Display", model);
}
public ActionResult PreviewWordDocument()
{
var image = Url.Content("~/Content/preview.jpeg");
return PartialView((object)image);
}
The document actionresult can get the model, but I want to know how can I get the values from the actionlink which will trigger the PreviewWordDocument action.
Thanks in advance, Laziale
The form can only be posted using the submit button to the URL given by its action attribute.
You can however send the form data to a different URL using the jQuery post method, manually validating the form before it is sent.
That way you can send the form data to the PreviewWordDocument controller method and handle the response in order to show the preview in the desired div.
(It will be helpful if you give an id to the form, so you can easily find it using jQuery)
So your click event handler for the preview link will look like this:
$("#previewLink").click(function(e) {
e.preventDefault();
if($("#YourFormId").valid()){
$("#dialogcontainer").dialog('open');
}
});
In the open function of the dialog you will post the form (which was already validated) to the preview controller method, using the jQuery ajax function. The response will be loaded into the dialogContent div:
$.ajax({
type: "POST",
url: $("#previewLink").attr("href"), //the preview controller method
data: $("#YourFormId").serialize(),
success: function (data) {
//load ajax response into the dialogContent div
$("#dialogcontent").html(data);
},
error: function(xhr, error) {
$("#YourFormId").prepend('<div id="ajaxErrors"></div>')
.html(xhr.responseText);
}
});
Now you will now be able to receive the whole document in the PreviewWordDocument action:
public ActionResult PreviewWordDocument(WordAutomation.Models.Document model)
{
var image = Url.Content("~/Content/preview.jpeg");
return PartialView((object)image);
}
in a HTML page when you click on a submit button all the input elements inside the form which the submit button resides in will posted to server, but when you click on a anchor (<a> tag ). you only send a request with a Get method and without posting any value.but if you want to send particular value to the server with this approach you can do it by query string.you have used following to make a request :
#Html.ActionLink("Preview", "PreviewWordDocument", "Home", null,
new { id = "previewLink" })
this will produce :
<a id="previewLink" href="/Home/PreviewWordDocument"> Preview </a>
which is incorrect.to pass any value to the server with ActionLink use 4th parameter like this :
#Html.ActionLink("Preview", "PreviewWordDocument", "Home",
new { id = "previewLink" }, null)
the result from this code would be :
Preview
cheers!

How do I display an additional partial view when a user clicks a button on the main view?

I want to click the button on the "main view" and populate the partial view in its own . Updated
I have a main view:
#{
using (Ajax.BeginForm("PastClaims", "Claim", FormMethod.Post, new AjaxOptions { UpdateTargetId = "update_panel", InsertionMode = InsertionMode.Replace }, new { #class = "form-horizontal" }))
{
<legend>Submit a Claim</legend>
#Html.EditorForModel()
<div class="controls">
<input id="btnCheckForClaims" type="submit" class="btn btn-primary" value="Submit Claim" />
</div>
}
I need to click the submit button then display this other view:
If I do below then on the page on the initial load it displays the div
<div id="update_panel">#Html.Partial("PastClaims")</div>
If I leave the div blank then I get a new partial view.
<div id="update_panel"></div>
if I leave them null like darrin suggested:
using (Ajax.BeginForm("PastClaims", "Claim", FormMethod.Post, new AjaxOptions { UpdateTargetId = "update_panel", InsertionMode = InsertionMode.Replace }, new { #class = "form-horizontal" }))
I am redirected to the same page (what I want) but the additional partial view is not displayed.
Thanks to Darrin below to get me this far.
You could use an Ajax.BeginForm in this case:
#using (Ajax.BeginForm(null, null, new AjaxOptions { UpdateTargetId = "update_panel", InsertionMode = InsertionMode.Replace }, new { #class = "form-horizontal"}))
{
#Html.EditorForModel()
<div class="controls">
<input id="btnOpenPartialView" type="submit" class="btn btn-primary" value="OpenPartialView" />
</div>
}
<div id="update_panel">
#Html.Partial("PartialView")
</div>
and then the corresponding controller action will return the partial view:
[HttpPost]
public ActionResult SomeAction()
{
// some processing ...
return PartialView("PartialView");
}
For Ajax.* helpers to work don't forget to include the jquery.unobtrusive-ajax.js script:
<script src="#Url.Content("~/Scripts/jquery.unobtrusive-ajax.js")" type="text/javascript"></script>
#Html.Partial is server code, if you want load partial after submit, then try this:
$("form").on('submit', function(event){
event.preventDefault();
var form = $(this);
$.ajax({
url: form.attr('action'),
type: form.attr('method'),
data: form.serialize(),
success: function(r) {
$('#update_panel').html(r);
}
});
});

How to pass selected dropdownlist value to Ajax.ActionLink in MVC 4?

I am trying to pass a Form value "CustomerID" (i.e.dropdownlist selected value) using Ajax.Actionlink in MVC 4. Can someone tell me what I am doing wrong here?
<div class="editor-label">
#Html.LabelFor(model => model.CustomerID, "Customer Name")
</div>
<div class="editor-field">
#Html.DropDownListFor(model => model.CustomerID, Model.CustomersList, "-- Select --")
#Html.ValidationMessageFor(model => model.CustomerID)
</div>
<div id="ApptsForSelectedDate">
#Ajax.ActionLink("Click here to view appointments",
"AppointmentsList",
new {id = Model.CustomerID},
new AjaxOptions
{
UpdateTargetId = "ApptsForSelectedDate",
HttpMethod = "GET",
InsertionMode = InsertionMode.Replace,
LoadingElementId = "progress"
}
)
</div>
<div id="progress">
<img src="../../Images/ajax-loader.gif" alt="loader image" />
</div>
My controller method looks like this:
public PartialViewResult AppointmentsList(int id)
{ ... }
You should use an Ajax.BeginForm and put the dropdown inside the form. This way the value will be automatically passed.
Unfortunately since you cannot nest html forms if you already have another form wrapping this markup you cannot use a nested form.
In this case you could use a normal link:
#Html.ActionLink(
"Click here to view appointments",
"AppointmentsList",
null,
new { id = "applink" }
)
and in a separate javascript file AJAXify it and append the necessary information to the query string by reading the selected dropdown value at the moment the AJAX request is sent:
$(function() {
$('#applink').click(function() {
$('#progress').show();
$.ajax({
url: this.href,
type: 'GET',
data: { id: $('#CustomerID').val() },
complete: function() {
$('#progress').hide();
},
success: function(result) {
$('#ApptsForSelectedDate').html(result);
}
});
return false;
});
});

Resources