Ajax BeginForm not calling action in controller - ajax

I have been trying to implement a system where a user can add/delete child entities of the current entity, however I have been having trouble using the Ajax.BeginForm helper method (this is my first real use of it). Basically when I click the submit button, it won't call the specified action in my controller.
I have searched for several hours now without success, most of the issues people have had before is due to certain libraries not being referenced, but I'm pretty sure that's not the issue here.
Anyway, here are the important parts of my code:
Partial View
#using MyProject.Domain.Entities;
#model MyProject.WebUI.ViewModels.UserCustomerViewModel
<div id = "meh222">
#using (
Ajax.BeginForm("AddCustomer", "User",
new AjaxOptions() { UpdateTargetId = "meh222", HttpMethod = "Post" })
)
{
<label>Customers</label>
#*#Ajax.ActionLink("Add Customer", "AddCustomer", "User", new { userID = Model.UserID, customerID = 1001 },
new AjaxOptions() { UpdateTargetId = "meh222", HttpMethod = "POST" }, new { #class = "standardbutton" })*#
<fieldset>
<legend>CustomersLegend</legend>
#Html.HiddenFor(m => m.UserID)
#Html.DropDownListFor(m => m.Customers, new SelectList(Model.AllCustomers, "CustomerID", "Name"))
<p>
<input type="submit" value="Add Customer" />
</p>
</fieldset>
}
<table class="tbl2" id="tbl2">
<thead>
<tr>
<th>CustomerID</th> <th>Name</th> <th>Actions</th>
</tr>
</thead>
<tbody>
#if (Model != null)
{
foreach (Customer item in Model.Customers)
{
<tr>
<td>
#Html.DisplayTextFor(i => item.CustomerID)
</td>
<td>
#Html.DisplayTextFor(i => item.Name)
</td>
<td>
#Ajax.ActionLink("Delete", "DeleteCustomer", "User", new { userID = Model.UserID, customerID = item.CustomerID },
new AjaxOptions() { UpdateTargetId = "meh222" }, new { #class = "standardbutton" })
</td>
</tr>
}
}
</tbody>
</table>
</div>
Main View
<div>
#{ Html.RenderPartial("CustomerPartial", Model.CustomerVM); }
</div>
Controller
[AcceptVerbs(HttpVerbs.Post)]
public PartialViewResult AddCustomer(UserCustomerViewModel vm)
{
return PartialView("CustomerPartial");
}
View Model
public class UserCustomerViewModel
{
public int UserID;
public IEnumerable<Customer> Customers { get; set; }
public IEnumerable<Customer> AllCustomers { get; set; }
}
Scripts in my _Layout
<script src="#Url.Content("~/Scripts/jquery-1.5.1.js")" type="text/javascript"></script>
<script src="#Url.Content("~/Scripts/jquery-1.5.1.min.js")" type="text/javascript"></script>
<script src="#Url.Content("~/Scripts/jquery-ui-1.8.11.js")" type="text/javascript"></script>
<script src="#Url.Content("~/Scripts/jquery-ui-1.8.11.min.js")" type="text/javascript"></script>
<script src="#Url.Content("~/Scripts/jquery.unobtrusive-ajax.js")" type="text/javascript"></script>
<script src="#Url.Content("~/Scripts/jquery.unobtrusive-ajax.min.js")" type="text/javascript"></script>
<script src="#Url.Content("~/Scripts/MicrosoftMvcAjax.js")" type="text/javascript"></script>
<script src="#Url.Content("~/Scripts/MicrosoftAjax.js")" type="text/javascript"></script>
<script src="#Url.Content("~/Scripts/modernizr-1.7.min.js")" type="text/javascript"></script>
Just a couple of notes:
If you look in my partial view, you can see an Ajax.ActionLink commented out. This was what I used before (and it worked), however I needed to hardcode the CustomerID, hence the change to Ajax.BeginForm so I can access the value of the DropDownList that is populated from the ViewModel's AllCustomers property.
The real controller action obviously has more processing, but that isn't the problem here as if I put a breakpoint in the action it isn't even hit.
I have added the list of scripts just so people know exactly what I am referencing in case that is the issue.
Does anyone have any ideas why my submit isn't accessing the AddCustomer action in my controller?
If I haven't decribed the issue properly or you need more information, please let me know and I will try and give more information.
Thanks very much.
----UPDATE----
Error data I got from Chrome's console
This is under the '500 Internal Server Error' in the console.
d.support.ajax.d.ajaxTransport.send jquery-1.5.1.min.js:19
d.extend.ajax jquery-1.5.1.min.js:19
e jquery.unobtrusive-ajax.min.js:5
(anonymous function) jquery.unobtrusive-ajax.min.js:5
E jquery-1.5.1.min.js:19
d.event.handle jquery-1.5.1.min.js:19
d.event.add.k.handle.m jquery-1.5.1.min.js:19

Related

Switch partial based on radio button in ASP.NET Core MVC

I don't know how to perform this in ASP.NET Core MVC.
I've got two radio buttons of the same group, I wish to switch a partial view based on the current radio button selection. I think I'll have to use js somehow but I don't know how.
Currently I wrote
Html.Kendo().RadioButton().Name("manual").Checked(true).HtmlAttributes(new { #name = "group1" }).Label("Manuale");
Html.Kendo().RadioButton().Name("guidata").Checked(true).HtmlAttributes(new { #name = "group1" }).Label("Guidata");
<div id="dyn_container"/>
But I don't know how to load data and eventually pass a model, any suggestions?
Thanks
The essence of RadioButton is actually an Input, so you can use the method of monitoring Input changes to determine how to continue to perform the following operations.
Below is my test code, you can refer to it:
View:
<table>
<tr>
<td class="Form_Label"><label for="txType">Select List:</label> </td>
<td>
#Html.Kendo().RadioButton().Name("manual").Checked(true).HtmlAttributes(new { #name = "group1",#value = "Manuale" }).Label("Manuale")
#Html.Kendo().RadioButton().Name("guidata").Checked(true).HtmlAttributes(new { #name = "group1",#value = "Guidata" }).Label("Guidata")
</td>
</tr>
</table>
<div id="dyn_container"></div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js" type="text/javascript"></script>
<script >
$('input:radio[name=group1]').change(function() {
var url = '/Home/Manuale';
if ($(this).val() === 'Guidata') {
url = '/Home/Guidata';
}
$("#dyn_container").load(url);
});
</script>
Then, you can execute the corresponding action in the controller by:
[HttpGet]
public ActionResult Manuale()
{
return PartialView("_Manuale");
}
[HttpGet]
public ActionResult Guidata()
{
return PartialView("_Guidata");
}
Test Result:
Update:
This is caused by inconsistency between your constructor and instantiation, you need to inject ILogger<_Page1Model> into the page.
Add this line of code in View:
#inject ILogger<_Page1Model> logger1
Then modify Html.PartialAsync:
#await Html.PartialAsync("_Page1", new _Page1Model(logger1));
Excuse me, I have a little bit modified your example (I don't have the original code under my hands so I wrote a new one).
I don't have a controller, using the RazorPages, so currently I've done this way
#page
#using Microsoft.AspNetCore.Mvc.Localization
#using Microsoft.AspNetCore.Mvc.RazorPages
#using Test.Localization
#using Test.Web.Pages
#using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Table
#using Volo.Abp.AspNetCore.Mvc.UI.Bundling.TagHelpers
#using Volo.Abp.Users
#model Test.Web.Pages.IndexModel
#inject IHtmlLocalizer<TestResource> L
#inject ICurrentUser CurrentUser
#section styles {
<abp-style src="/Pages/Index.css" />
}
#section scripts {
<abp-script src="/Pages/Index.js" />
}
<div class="container">
<table>
<tr>
<td class="Form_Label"><label for="txType">Select List:</label> </td>
<td>
#Html.RadioButton("group1","HotelGrandPlaza", false)
#Html.RadioButton("group1","Test", false)
</td>
</tr>
</table>
<div id="project" style="display:none">
#await Html.PartialAsync("_Page1", new _Page1Model());
</div>
<div id="engineering" style="display:none">
#{await Html.RenderPartialAsync("_Page2", new _Page2Model());}
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js" type="text/javascript"></script>
<script >
$('input:radio[name=group1]').change(function() {
if ($(this).val() === 'Test') {
$("#project").hide();
$("#engineering").show();
} else {
{
$("#project").show();
$("#engineering").hide();
}
}
});
</script>
</div>
In this case when I switch it works... but problems arrive when I have a constructor with Dependency Injection....
Just with this simple case
public class _Page1Model : PageModel
{
private readonly ILogger<_Page1Model> _logger;
public _Page1Model(ILogger<_Page1Model> logger)
{
_logger = logger;
}
public void OnGet()
{
}
}
}
I can't use the cshtml I've defined before... any suggestions?
Thanks

MVC model values not getting passed to controller

I am trying out with very basic MVC project using MVC 3.0 and Razor. Referring the turorial at this link.
I have created a strongly typed view for editing the Contacts using my model class called "Contact".
namespace Practice.Models
{
public class Contact
{
public string firstName;
public string lastName;
public string mobileNumber;
}
}
The "Index" method displays all the contacts using a list type view. When I click on "Edit" link against a contact, it displays the contact details in textboxes using an Edit View.
However, when I submit the Edit form, I am not getting the model values in controller action method. It shows null for each property. What exactly I may be missing here in such simple example?
DirectoryController
[HttpPost]
public ViewResult Edit(Contact model)
{
contactRepository.Update(model);
return View("Details", model);
}
View
#model Practice.Models.Contact
#{
ViewBag.Title = "Edit";
}
<h2>Edit</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>
#using (Html.BeginForm("Edit","Directory"))
{
#Html.ValidationSummary(true)
<fieldset>
<legend>Contact</legend>
#Html.TextBoxFor(m => m.firstName)
#Html.TextBoxFor(m => m.lastName)
#Html.TextBoxFor(m => m.mobileNumber)
<p>
<input type="submit" value="Save" />
</p>
</fieldset>
}
<div>
#Html.ActionLink("Back to List", "Index")
</div>
You are missing { get; set; } on your model properties

Formcollection doesn't extract data from form MVC

I have trouble with formcollection.
I have some form in view, and two submit buttons both with unique name="". On debug I get on controller in formcollection all data except "name" of submitted button... I don't know why, 'cos I use this in other forms and there it works good. So I look at the code, but I couldn't find any differencies in using formcollection on not working formcol and working formcol. I tried rename buttons, move them, add referencies which I thought that could help... Nothing. On every submit skip my condition because it give me back only "false" and formcollection my "upload" or "save" button on onclick doesn't contain...
So I would like to ask you for help with this. Can you tell me where could be an error? Thanks to all!
This is in controller:
[HttpPost]
public ActionResult EditUser(EditUserVM model, int id, FormCollection c)
{
//c["upload"] is everytime set to null, 'cos c does't contain it
if (c["upload"] != null)
{
//.... some code
return RedirectToAction("Index", "Home");
}
if (ModelState.IsValid)
{
//.... next code
}
return View("EditUser", model);
}
This is in View:
#model PrukazOnline.ViewModels.EditUserVM
#{
ViewBag.Title = "EditUser";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<script type="text/javascript" src="#Url.Content("~/Scripts/jquery.validate.min.js")"></script>
<script type="text/javascript" src="#Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")"></script>
<script type="text/javascript" src="#Url.Content("~/Scripts/jquery.unobtrusive-ajax.min.js")"></script>
#using (Html.BeginForm("EditUser", "User", null, FormMethod.Post, new { #class = "form-horizontal", id = "formstep", enctype = "multipart/form-data" }))
{
#*Here is some code - #Html.TextBoxFor(x => x.something) and #Html.ValidationMessageFor(x => x.something) - all of these are in formcollection*#
.
.
.
.
<div>
<input type="submit" value="Nahrát" class="upl" name="upload" id="upload" />
</div>
<div class="submit_buttons">
<input type="submit" name="save" id="save" value="Uložit" />
</div>
}
Issue is in multiple submit inputs in single form. There will only clicked button in FormCollection.
I suppose you try to vary form processing base on clicked button, in this case it's better to use different Actions for each button like this:
View:
<div>
<input type="submit" value="Nahrát" class="upl" name="upload" id="upload" />
</div>
<div class="submit_buttons">
<input type="submit" name="save" id="save" value="Uložit" />
</div>
Controller:
[HttpParamAction]
[HttpPost]
public ActionResult Upload(EditUserVM model)
{
...
}
[HttpParamAction]
[HttpPost]
public ActionResult Save(EditUserVM model)
{
...
}

partial view display with targeted div in MVC3 Razor view engine

My Controller Action is:
public ActionResult PVInPage()
{
return View();
}
public ActionResult ViewPage2()
{
return PartialView();
}
My Main View:
#using (Html.BeginForm("ViewPage2", "PartialViewInPage"))
{
<input type="submit" value="Call Page Two" />
}
<div id="DisplayPartilView">
#*display partial view *#
</div>
My Partial view Is :
#{
ViewBag.Title = "View Page 2";
}
<div style="width:500px; height:200px; background-color:Gray" >
<h1> This is my Partial view </h1>
</div>
Now I want to do : when i click submit button in my main view then my partial view arise in
My main view inner div with id="DisplayPartilView".
Thanks for response
If you want to load data/html into a page without navigating to a different page you need to use Ajax.
ASP.Net MVC provides a set of helpers to work with Ajax (they are all use jQuery.Ajax under the hood so you can always drop back to one level and write your ajax calls by hand).
But in your case the Ajax.BeginForm provides everything what you need:
So change your main view to:
#using (Ajax.BeginForm("ViewPage2", "PartialViewInPage",
new AjaxOptions() { UpdateTargetId = "DisplayPartilView" }))
{
<input type="submit" value="Call Page Two" />
}
<div id="DisplayPartilView">
#*display partial view *#
</div>
And to make it work you need to reference the following script in your main view or in your layout file after jQuery:
<script src="#Url.Content("~/Scripts/jquery.unobtrusive-ajax.js")" type="text/javascript"></script>
#using (Html.BeginForm("ViewPage2", "PartialViewInPage"))
will refresh page, that's why you need ajax
.serialize() to get data from all inputs and .ajax() to make post request, then set partial:
$('#DisplayPartilView').html(response);
In my project i am doing like this it's below
this is my button which is i click then my partial view load in my div like this
<script type="text/javascript">
$(function () {
$("#btnLode").click(function () {
$("#LodeForm").load("/City/ShowAllState", function () {
alert("Your page loaded Successfully !!!!!!!");
});
});
});
</script>
<div id="LodeForm">
</div>
and this is another solution for this problem
#using (Ajax.BeginForm("SearchCountry", "City",
new AjaxOptions
{
InsertionMode = InsertionMode.Replace,
HttpMethod = "Get",
LoadingElementId = "ajax-loader",
UpdateTargetId = "CountryListID",
}))
{
<input type="submit" value="search Country" data-autocomplete-source="#Url.Action("SearchCountry", "City")" />
}
<div id="CountryListID">
</div>
i think this will help you

MVC4 - Ajax.BeginForm and Partial view gives 'undefined'

I'm working on an activity booking and I'm having trouble using ajax.beginform with a partial view. When I click submit, it just goes to a new page and there is an 'undefined' in the top left corner. I have "../../Scripts/jquery.unobtrusive-ajax.min.js" in my layout page. What I want to do is when the user submits the form, the div "AjaxTest" gets updated with the partial view and the form is under the search results.
Here is what I have so far (I took out all the structure and styling so its easier to read):
Main View - Activities
#model Project.Models.ActivityModel
<div id="AjaxTest"></div>
#using (Ajax.BeginForm(new AjaxOptions
{
UpdateTargetId = "AjaxTest",
InsertionMode = InsertionMode.Replace,
HttpMethod = "POST"
}))
{
#Html.ValidationSummary(true)
#Html.TextBoxFor(x => x.Activity_CityName)
<div class="editor-label">
<strong>#Html.LabelFor(x => x.Activity_StartDate)</strong>
</div>
<div class="editor-field">
<input id="checkin" type="text" name="Activity_StartDate" />
</div>
#Html.TextBoxFor(x => x.Activity_EndDate)
#Html.DropDownListFor(x => x.Activity_NumAdults, AdultNum)
#Html.DropDownListFor(x => x.Activity_NumChildren)
#Html.DropDownListFor(x => x.Activity_ChildAge1, ChildAge)
#Html.DropDownListFor(x => x.Activity_ChildAge2, ChildAge)
#Html.DropDownListFor(x => x.Activity_ChildAge3, ChildAge)
<div class="submitbutton">
<input data-inline="true"type="submit" id="activity_search" value="Search" />
</div>
}
Controller
[HttpPost]
public ActionResult Activities(ActivityModel activitysubmission) {
return PartialView("PartialActivities_Success", activitysubmission);
}
Partial View - PartialActivities_Success
#model Project.Models.ActivityModel
<p>City: #Model.Activity_CityName</p>
<p>StartDate: #Model.Activity_StartDate</p>
<p>EndDate: #Model.Activity_EndDate</p>
<div>
<p><strong>Ticket</strong></p>
<p>Number of Adults: #Model.Activity_NumAdults</p>
<p>Number of Children: #Model.Activity_NumChildren</p>
<p>Child 1 age: #Model.Activity_ChildAge1</p>
<p>Child 2 age: #Model.Activity_ChildAge2</p>
<p>Child 3 age: #Model.Activity_ChildAge3</p>
</div>
Scripts in Layout Page
<script src="../../Scripts/jquery.unobtrusive-ajax.min.js" type="text/javascript"> </script>
<script src="../../Scripts/xdate.js" type="text/javascript"></script>
<script src="../../Scripts/xdate.i18n.js" type="text/javascript"></script>
<script src="#System.Web.Optimization.BundleTable.Bundles.ResolveBundleUrl("~/Scripts/js")"></script>
<script>
$(document).bind("mobileinit", function() {
// As of Beta 2, jQuery Mobile's Ajax navigation does not work in all cases (e.g.,
// when navigating from a mobile to a non-mobile page, or when clicking "back"
// after a form post), hence disabling it.
$.mobile.ajaxEnabled = true; // originally false.
});
</script>
I noticed one mistake in the code. Your div has an id Ajaxtest but the parameter you are passing to BeginRequest is AjaxTest the T is capital
Are you using MVC 4? I would make sure that UnobtrusiveJavaScriptEnabled is set to true in your WebConfig file. I believe it is by default, though. The only other thing I can think of is to verify that you have your other jQuery files and that they're being loaded in the right order. If you load your unobrusive jQuery file before the main one then it won't work.
You haven't specified which action to call when posting the Ajax form. Try changing it to this:
#using (Ajax.BeginForm("Activities", new AjaxOptions
{
UpdateTargetId = "AjaxTest",
InsertionMode = InsertionMode.Replace,
HttpMethod = "POST"
}))

Resources