ASP.Net MVC - Ajax.BeginRequest() not generating an ajax request - asp.net-mvc

This is my Test.cshtml:
#using(Ajax.BeginForm("Test", new AjaxOptions()))
{
<p>
Some String: <input name="someString" type="text" />
</p>
<button type="submit">Submit</button>
}
Where jquery-1.4.4.min.js is included by the layout.
My Controller has the following two actions:
public ActionResult Test()
{
return View();
}
[HttpPost]
public ActionResult Test(string someString)
{
if (Request.IsAjaxRequest())
return Json("Okey-dokey");
return View();
}
It seems that when I hit submit, it always does a full post-back, Request.IsAjaxRequest() is never true!
What gives?

George,
Please make sure that you include the script jquery.unobtrusive-ajax.js in your layout page.
counsellorben

I see no ajax functionality in your code examples.

You need to use Something like this to get ajax functionality
using (Ajax.BeginForm("Test", "ControllerName" ,null,
new AjaxOptions { OnComplete = "FunctionToCallOnSuccess" }))

It is post, indeed.
You should use AJAX call, like this:
$(function(){
$( "#myButton" ).click(function(){
$.getJSON("/Controller/Test", {someString: $("#someString").val()}, function(data){
alert(data);
}
});
});
and in your form:
<p>
Some String: <input name="someString" id="someString" type="text" />
</p>
<button type="button">Submit</button>
This should work.

Related

ASP.NET MVC - redirect after form submit

I have a ASP.NET MVC website and a "Configuration" view with a form.
When I submit the form, I would like to do some stuff and then Redirect to my "Initialization" ViewResult... How to do it ?
My form :
#using (Html.BeginForm("Save", "Home", FormMethod.Post, new { id = "Config" }))
{
// Some fields
<input type="submit" value="Save" />
}
then, the "Save" action :
[HttpPost]
[ValidateAntiForgeryToken()]
public async Task<RedirectToRouteResult> Save(Config websiteConfiguration)
{
// Do some stuff
bool ok = await myMethod();
if(ok)
{
return RedirectToAction("Initialization");
}
}
I tried other possibilities but I don't manage to get it work...
Up, I still have the problem...
Not sure if this issue was with an earlier version of MVC, but I have often forgotten that the [HttpPost] label may be placed above an ActionResult in the controller and not just above a JsonResult.
So the simplest MVC-style answer would be just use Html.BeginForm and post to the ActionResult (with the [HttpPost] attribute), wherein you execute your logic, then call RedirectToAction at end after you have handled the post controller side.
This seems far easier than all the client-side fiddles, e.g. window.location.href = '' etc...
This is what your Form Post method should look like
<HttpPost>
<ActionName("Respond")>
Function Respond_post(viewModel As FormsRespondModel) As ActionResult
viewModel.form.formId = Guid.Parse(Request("formId"))
viewModel.form.loadForm(Guid.Parse(Request("formId")))
If (viewModel.form.formNotifications.onSuccess = "redirectOnSuccess") Then
Return Redirect(viewModel.form.formNotifications.redirectUrl)
End If
Return RedirectToRoute("form_finished")
End Function
Try this :
<input id="btnSave" name="btnSave" type="submit" value="Save" onclick="window.location = '#Url.Action("Action_Name", "Controller_Name")'; return false;" />

ASP.NET MVC Html.BeginForm decodes URL

I'm requesting ASP.NET MVC the controller using the URL like this:
http://mysite.com/controller/myaction/Invalid%23name%25x
where Invalid%23name%25x is a parameter to
public ActionResult MyAction(string id) {
return View();
}
The GET request works fine.
MyAction view looks like this:
#using (Html.BeginForm()) {
...
<input name="Save" type="submit" value="Save" />
}
The generated HTML is:
<form action="/Controller/MyAction/Invalid#name%x" method="post">
...
<input name="Save" type="submit" value="Save" />
</form>
When I click on "Save", the form gets posted and the POST request goes to
http://mysite.com/controller/myaction/Invalid#name%x
i.e. the initial URL is decoded. This means the the POST action receives only the first part of the parameter - "Invalid"
[HttpPost]
public ActionResult MyAction(string id, ...) {
return View();
}
How can I prevent Html.BeginForm from decoding the initial URLs in order to preserve the initial state?
Pass ActionName and Controller in your form
#using (Html.BeginForm("ActionName", "Controller")) {
I would personally recommend you not to use id as string because as you have seen string can have many words in it.. let it mean what usually it does(numeric value).
use something like http://mysite.com/controller/myaction?Name=Invalid%23name%25x
public ActionResult MyAction(string Name) {
return View();
}
I suppose this would work for you..

Unobtrusive Javascript - And Ajax Requests

I've got a simple example here. Basically a form which when submitted will reload itself via an ajax request. The problem is when this happens, the unobtrusive javascript no longer works. I assume I could add the validate and unobtrusive files in the html i get back from the ajax call, but there must be an easier way to re-wire the validators, no?
Notice I'm hijacking my submit button in order to do an AJAX request which will replace the form in the dom, from the html which is returned from the ajax request.
Model:
public class Foo
{
public int Bar { get; set; }
}
Controller:
public class FooController : Controller
{
public ActionResult Index()
{
return View(new Foo{});
}
[HttpPost]
public ActionResult Form(Foo model)
{
return View(model);
}
[HttpPost]
public ActionResult Index(Foo model)
{
return View();
}
}
Index.cshtml
#model PartialPostBackValidation.Models.Foo
#{
ViewBag.Title = "Index";
}
<h2>#Html.ActionLink("Index", "Index")</h2>
<script src="#Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script>
<script src="#Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script>
<script>
$(function () {
$("body").on("click", ".ajax-submit", function () {
var form = $(this).parents("form");
$.post(
form.attr("action"),
form.serialize(),
function (html) {
form.replaceWith(html);
}
);
return false;
});
});
</script>
#{Html.RenderPartial("Form");}
Form.cshtml
#model PartialPostBackValidation.Models.Foo
#{
ViewBag.Title = "Index";
Layout = null;
}
#using (Html.BeginForm("Form", "Foo")) {
#Html.ValidationSummary(true)
<fieldset>
<legend>Foo</legend>
<div class="editor-label">
#Html.LabelFor(model => model.Bar)
</div>
<div class="editor-field">
#Html.TextBoxFor(model => model.Bar)
#Html.ValidationMessageFor(model => model.Bar)
</div>
<p>
<input type="submit" value="Create" class="ajax-submit" />
</p>
</fieldset>
}
To get the validation to work you simply have to re-enable it on the form once content is loaded dynamically:
$('#form-id').removeData('validator');
$('#form-id').removeData('unobtrusiveValidation');
$.validator.unobtrusive.parse('#form-id'); <<<<<< Just having this could be enough but some people complain that without removingData first it doesn’t always work.
p.s. Ofcourse you're going to need to add an id attribute to your #using (Html.BeginForm("Form", "Foo"))

Why Ajax.BeginForm does not pass form values?

I'm trying to show a partial view via calling Ajax.BeginForm, but I can't receive the values of my form(I need to get the value of hidden input, bookId, in controller, e.g 5).
// View
#using (Ajax.BeginForm("Detail", "Books", new AjaxOptions { HttpMethod = "GET", UpdateTargetId = "ShowBookDiv" }))
{
<input type="hidden" id="bookId" value="5" />
<input type="submit" id="sBtn" value="Details" />
}
// Controller
[HttpGet]
public ActionResult Detail(string bookId)
{
if (Request.IsAjaxRequest())
{
var a = Request["bookId"].ToString();
// some code to get details
return PartialView("ShowBooks", details);
}
...
}
When I trace the code in Controller bookId is null!
I've added the "name" property to hidden field and it works !!! really strange!
<input type="hidden" name="bookId" id="bookId" value="5" />
Ajax.BeginForm is a pain, IMO.
I would Use $.ajax from JQuery Ajax API :
http://api.jquery.com/jQuery.ajax
here is a good example for you to see how it works :
http://www.tugberkugurlu.com/archive/working-with-jquery-ajax-api-on-asp-net-mvc-3-0-power-of-json-jquery-and-asp-net-mvc-partial-views
Posting the whole form requires a little bit of work (in terms of validation, etc.) but you will have complete control over the action if you are good with JavaScript.

ASP.NET MVC ActionLink and post method

Can anyone tell me how can I submit values to Controller using ActionLink and POST method?
I don't want to use buttons.
I guess it has something with jquery.
If you're using ASP MVC3 you could use an Ajax.ActionLink(), that allows you to specify a HTTP Method which you could set to "POST".
You can't use an ActionLink because that just renders an anchor <a> tag.
You can use a jQuery AJAX post.
Or just call the form's submit method with or without jQuery (which would be non-AJAX), perhaps in the onclick event of whatever control takes your fancy.
You can use jQuery to do a POST for all your buttons. Just give them the same CssClass name.
Use "return false;" at the end of your onclick javascript event if you want to do a server side RedirectToAction after the post otherwise just return the view.
Razor Code
#using (Html.BeginForm())
{
#Html.HiddenFor(model => model.ID)
#Html.ActionLink("Save", "SaveAction", "MainController", null, new { #class = "saveButton", onclick = "return false;" })
}
JQuery Code
$(document).ready(function () {
$('.saveButton').click(function () {
$(this).closest('form')[0].submit();
});
});
C#
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult SaveAction(SaveViewModel model)
{
// Save code here...
return RedirectToAction("Index");
//return View(model);
}
#Aidos had the right answer just wanted to make it clear since it is hidden inside a comment on his post made by #CodingWithSpike.
#Ajax.ActionLink("Delete", "Delete", new { id = item.ApkModelId }, new AjaxOptions { HttpMethod = "POST" })
Here was an answer baked into the default ASP.NET MVC 5 project I believe that accomplishes my styling goals nicely in the UI. Form submit using pure javascript to some containing form.
#using (Html.BeginForm("Logout", "Account", FormMethod.Post, new { id = "logoutForm", #class = "navbar-right" }))
{
<a href="javascript:document.getElementById('logoutForm').submit()">
<span>Sign out</span>
</a>
}
The fully shown use case is a logout dropdown in the navigation bar of a web app.
#using (Html.BeginForm("Logout", "Account", FormMethod.Post, new { id = "logoutForm", #class = "navbar-right" }))
{
#Html.AntiForgeryToken()
<div class="dropdown">
<button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown">
<span class="ma-nav-text ma-account-name">#User.Identity.Name</span>
<i class="material-icons md-36 text-inverse">person</i>
</button>
<ul class="dropdown-menu dropdown-menu-right ma-dropdown-tray">
<li>
<a href="javascript:document.getElementById('logoutForm').submit()">
<i class="material-icons">system_update_alt</i>
<span>Sign out</span>
</a>
</li>
</ul>
</div>
}
ActionLink will never fire post. It always trigger GET request.
Use the following the Call the Action Link:
<%= Html.ActionLink("Click Here" , "ActionName","ContorllerName" )%>
For submitting the form values use:
<% using (Html.BeginForm("CustomerSearchResults", "Customer"))
{ %>
<input type="text" id="Name" />
<input type="submit" class="dASButton" value="Submit" />
<% } %>
It will submit the Data to Customer Controller and CustomerSearchResults Action.
This is taken from the MVC sample project
#if (ViewBag.ShowRemoveButton)
{
using (Html.BeginForm("RemoveLogin", "Manage"))
{
#Html.AntiForgeryToken()
<div>
#Html.Hidden("company_name", account)
#Html.Hidden("returnUrl", Model.returnUrl)
<input type="submit" class="btn btn-default" value="Remove" title="Remove your email address from #account" />
</div>
}
}
Use this link inside Ajax.BeginForm
#Html.ActionLink(
"Save",
"SaveAction",
null,
null,
onclick = "$(this).parents('form').attr('action', $(this).attr('href'));$(this).parents('form').submit();return false;" })
;)
My Solution to this issue is a fairly simple one. I have a page that does a customer search one by the whole email and the other by a partial, the partial pulls and displays a list the list has an action link that points to a actionresult called GetByID and passes in the id
the GetByID pulls the data for the selected customer then returns
return View("Index", model);
which is the post method
This has been a difficult problem for me to solve. How can I build a dynamic link in razor and html that can call an action method and pass a value or values to a specific action method? I considered several options including a custom html helper. I just came up with a simple and elegant solution.
The view
#model IEnumerable<MyMvcApp.Models.Product>
#using (Html.BeginForm()) {
<table>
<thead>
<tr>
<td>Name</td>
<td>Price</td>
<td>Quantity</td>
</tr>
</thead>
#foreach (Product p in Model.Products)
{
<tr>
<td>#p.Name</td>
<td>#p.Price.ToString()</td>
<td>#p.Quantity.ToString()</td>
</tr>
}
</table>
}
The action method
public ViewResult Edit(Product prod)
{
ContextDB contextDB = new ContextDB();
Product product = contextDB.Products.Single(p => p.ProductID == prod.ProductId);
product = prod;
contextDB.SaveChanges();
return View("Edit");
}
The point here is that Url.Action does not care whether the action method is a GET or a POST. It will access either type of method. You can pass your data to the action method using
#Url.Action(string actionName, string controllerName, object routeValues)
the routeValues object. I have tried this and it works. No, you are not technically doing a post or submitting the form but if the routeValues object contains your data, it doesnt matter if its a post or a get. You can use a particular action method signature to select the right method.
I have done the same issue using following code:
#using (Html.BeginForm("Delete", "Admin"))
{
#Html.Hidden("ProductID", item.ProductID)
<input type="submit" value="Delete" />
}
This is my solution for the problem.
This is controller with 2 action methods
public class FeedbackController : Controller
{
public ActionResult Index()
{
var feedbacks =dataFromSomeSource.getData;
return View(feedbacks);
}
[System.Web.Mvc.HttpDelete]
[System.Web.Mvc.Authorize(Roles = "admin")]
public ActionResult Delete([FromBody]int id)
{
return RedirectToAction("Index");
}
}
In View I render construct following structure.
<html>
..
<script src="~/Scripts/bootbox.min.js"></script>
<script>
function confirmDelete(id) {
bootbox.confirm('#Resources.Resource.AreYouSure', function(result) {
if (result) {
document.getElementById('idField').value = id;
document.getElementById('myForm').submit();
}
}.bind(this));
}
</script>
#using (Html.BeginForm("Delete", "Feedback", FormMethod.Post, new { id = "myForm" }))
{
#Html.HttpMethodOverride(HttpVerbs.Delete)
#Html.Hidden("id",null,new{id="idField"})
foreach (var feedback in #Model)
{
if (User.Identity.IsAuthenticated && User.IsInRole("admin"))
{
#Html.ActionLink("Delete Item", "", new { id = #feedback.Id }, new { onClick = "confirmDelete("+feedback.Id+");return false;" })
}
}
...
</html>
Point of interest in Razor View:
JavaScript function confirmDelete(id) which is called when the link generated with #Html.ActionLink is clicked;
confirmDelete() function required id of item being clicked. This item is passed from onClick handler confirmDelete("+feedback.Id+");return false; Pay attention handler returns false to prevent default action - which is get request to target. OnClick event for buttons could be attached with jQuery for all buttons in the list as alternative (probably it will be even better, as it will be less text in the HTML page and data could be passed via data- attribute).
Form has id=myForm, in order to find it in confirmDelete().
Form includes #Html.HttpMethodOverride(HttpVerbs.Delete) in order to use the HttpDelete verb, as action marked with the HttpDeleteAttribute.
In the JS function I do use action confirmation (with help of external plugin, but standard confirm works fine too. Don't forget to use bind() in call back or var that=this (whatever you prefer).
Form has a hidden element with id='idField' and name='id'. So before the form is submitted after confirmation (result==true), the value of the hidden element is set to value passed argument and browser will submit data to controller like this:
Request URL:http://localhost:38874/Feedback/Delete
Request Method:POST Status Code:302 Found
Response Headers
Location:/Feedback
Host:localhost:38874
Form Data X-HTTP-Method-Override:DELETE id:5
As you see it is POST request with X-HTTP-Method-Override:DELETE and data in body set to "id:5". Response has 302 code which redirect to Index action, by this you refresh your screen after delete.
I would recommend staying pure to REST principles and using an HTTP delete for your deletes. Unfortunately HTML Specs only has HTTP Get & Post. A tag only can a HTTP Get. A form tag can either do a HTTP Get or Post. Fortunately if you use ajax you can do a HTTP Delete and this is what i recommend. See the following post for details: Http Deletes
Calling $.post() won't work as it is Ajax based. So a hybrid method needs to be used for this purpose.
Following is the solution which is working for me.
Steps:
1. Create URL for href which calls the a method with url and parameter
2. Call normal POST using JavaScript method
Solution:
In .cshtml:
View
Note: the anonymous method should be wrapped in (....)()
i.e.
(function() {
//code...
})();
postGo is defined as below in JavaScript.
Rest are simple..
#Url.Action("View") creates url for the call
{ 'id': #receipt.ReceiptId } creates parameters as object which is in-turn converted to POST fields in postGo method. This can be any parameter as you require
In JavaScript:
(function ($) {
$.extend({
getGo: function (url, params) {
document.location = url + '?' + $.param(params);
},
postGo: function (url, params) {
var $form = $("<form>")
.attr("method", "post")
.attr("action", url);
$.each(params, function (name, value) {
$("<input type='hidden'>")
.attr("name", name)
.attr("value", value)
.appendTo($form);
});
$form.appendTo("body");
$form.submit();
}
});
})(jQuery);
Reference URLs which I have used for postGo
Non-ajax GET/POST using jQuery (plugin?)
http://nuonical.com/jquery-postgo-plugin/
jQuery.post() will work if you have custom data. If you want to post existing form, it's easier to use ajaxSubmit().
And you don't have to setup this code in the ActionLink itself, since you can attach link handler in the document.ready() event (which is a preferred method anyway), for example using $(function(){ ... }) jQuery trick.
Came across this needing to POST from a Search (Index) page to the Result page. I did not need as much as #Vitaliy stated but it pointed me in the right direction. All I had to do was this:
#using (Html.BeginForm("Result", "Search", FormMethod.Post)) {
<div class="row">
<div class="col-md-4">
<div class="field">Search Term:</div>
<input id="k" name="k" type="text" placeholder="Search" />
</div>
</div>
<br />
<div class="row">
<div class="col-md-12">
<button type="submit" class="btn btn-default">Search</button>
</div>
</div>
}
My Controller had the following signature method:
[HttpPost]
public async Task<ActionResult> Result(string k)

Resources