I implemented a small test that is based on Scott Guthrie article
http://weblogs.asp.net/scottgu/archive/2010/07/27/introducing-asp-net-mvc-3-preview-1.aspx
But my controller action thinks that object passed to it is null, even though I used JSON.stringify on it and packed data to it - I followed the article exactly.
In my html
#using (Html.BeginForm("SomeAction", "ControllerName", FormMethod.Post, new { id = "FormID" })) {
<div class="editor-field">#Html.EditorFor(model => model.Date)</div>
<div class="editor-field">#Html.EditorFor(model => model.Id)</div>
<div class="editor-field">#Html.EditorFor(model => model.Name)</div>
<input type="button" value="save" onclick="Save();" />
}
In my model file
namespace MyNamespace.Models
{
public class MyModel
{
public string Id { get; set; }
public string DateReceived { get; set; }
public string Name { get; set; }
}
}
In my js
function Save() {
var myModelObj = { Id: $("#Id").val(),
DateReceived: $("#DateReceived").val(),
Name: $("#Name").val()
};
$.ajax({
type: "POST",
url: "/ControllerName/SomeAction",
data: JSON.stringify(myModelObj),
cache: false,
// dataType: "json",
success: function (data) {
alert('success!');
},
error: function (XMLHttpRequest, textStatus, errorThrown) {
alert('error');
alert(XMLHttpRequest + "<br />" + textStatus + "<br />" + errorThrown);
}
});
In my controller
[HttpPost]
public ActionResult SomeAction(MyModel modelObj )
{
using (StreamWriter sw = new StreamWriter("/test.txt") )
{
sw.Write(modelObj.Id);
}
return null;
}
When I put a break point on sw.Write...statement, modelObj.Id is null.
Am I missing something or is there anything else that needs to be wired up? Thanks!
I think you need to add the contentType and dataType options to your ajax call.
contentType: 'application/json, charset=utf-8',
dataType: 'json',
Related
Small help required
1) I have created an html Dropdown in MVC view like this
<select name="Associateddl" id="Associateddl"></select>
2)I am appending the options to the dropdownlist using Jquery Ajax like
$.ajax({
type: 'POST',
contentType: "application/json; charset=utf-8",
url: 'customservice.asmx/getallmember',
dataType: 'JSON',
success: function (response) {
var getData = JSON.parse(response.d);
console.log(getData.length);
if (getData.length > 0) {
$("#msg").hide();
$.each(getData, function (i, item) {
var optiontext = "";
optiontext = "<option value='" + item.Aid + "'>" + item.AMail + "</option>";
$("#Associateddl").append(optiontext);
});
}
else {
$("#msg").append("<p style='color:red'><b>Currently there are no members ,Please Add !!</b></p>");
}
},
error: function (err) {
//alert(err);
}
});
3)Now i want to retrive the dropdown selected value to controller from View.
My Model:
public class Event
{
[DisplayName("Event Name")]
[Required(ErrorMessage ="Event Name is Mandatory...")]
public string Eventname { get; set; }
[DisplayName("Event Year")]
[Required(ErrorMessage ="Enter the Year...")]
public int Year { get; set; }
[DisplayName("Associate ID")]
[Required(ErrorMessage ="Associate ID is required...")]
public string Associateddl { get; set; }
}
My Controller:
[HttpPost]
public ActionResult Index(Event eve)
{
string ename = eve.Eventname;
int eyr = eve.Year;
string eassociate = eve.Associateddl; //Here i want to retrive the dropdownselected Value
return View();
}
Please help me to get the Html dropdown seleted value to Controller from View.
Here is an example on how you can see the value of the ddl in the controller. I will get you an ASP.NET Fiddle you can click on that will host the solution.
web service
[System.Web.Script.Services.ScriptService]
public class Service1 : System.Web.Services.WebService
{
[WebMethod]
public string getallmember()
{
var drop2 = new List<SelectListItem>();
SelectListItem sli1 = new SelectListItem { Text = "MoreOptions1", Value = "1" };
SelectListItem sli2 = new SelectListItem { Text = "MoreOptions2", Value = "2" };
drop2.Add(sli1);
drop2.Add(sli2);
//GET NewtonSoft
var json = JsonConvert.SerializeObject(drop2);
return json;
}
Controller
public class HomeController : Controller
{
[HttpPost]
public ActionResult Tut118(string Associateddl)
{
//put breakpoint here
return View();
}
public ActionResult Tut118()
{
return View();
}
View
#{
Layout = null;
}
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>Tut118</title>
<script src="~/Scripts/jquery-1.12.4.min.js"></script>
<script type="text/javascript">
$(function () {
$("#theButton").click(function () {
$.ajax({
type: "Post",
url: "customservice.asmx/getallmember",
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function (response) {
$("#Associateddl").empty();
var theData = JSON.parse(response.d);
$.each(theData, function (i, anObj) {
$("#Associateddl").append($('<option>').text(anObj.Text).attr('value', anObj.Value));
});
}
,
error: function (request, status, error) {
alert(error);
}
});
})
})
</script>
</head>
<body>
<div>
#using (Html.BeginForm())
{
<input type="button" id="theButton" value="click to get ddl" />
<select name="Associateddl" id="Associateddl"></select>
<input type="submit" value="click after selecting ddl" />
}
</div>
</body>
</html>
I've coded for multiple values that resides inside listbox on button click. I have used autocomplete textbox to get the required value along with its id. Then i managed to add those values inside the listbox. Now what i want is to pass id's against those values in listbox instead of names. Below is my code that I'm running.
StudentBatch.cs
public string studentId { get; set; }
public string StudentName { get; set; }
public List<string> selectedids { get; set; }
public List<string> names { get; set; }
public List<string> SelectedNames { get; set; }
Create.cshtml
#using (Html.BeginForm("Create", "Student", FormMethod.Post))
{
<div class="form-group">
<div class="col-md-12">
#Html.EditorFor(model => model.StudentName, new { id = "StudentName" })
<input type="button" value="Add Text" id="addtypevalue" />
<div id="typevaluelist"></div>
</div>
</div>
<div id="new" style="display:none;">
<div class="typevalue">
<input type="text" name="typevalue" />
<button type="button" class="delete">Delete</button>
</div>
</div>
<div id="hiddensq">
</div>
for (int i = 0; i < Model.names.Count; i++)
{
#Html.Hidden("UserValues", Model.names[i]);
}
#Html.ListBoxFor(m => m.SelectedNames, new SelectList(Model.names))
<div id="partialDiv">
#{
Html.RenderPartial("GetListBox", Model);
}
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Create" class="btn btn-default" />
</div>
</div>
}
<script type="text/javascript">
$(document).ready(function () {
$("#StudentName").autocomplete({
//autocomplete: {
// delay: 0,
// minLength: 1,
source: function (request, response)
{
$.ajax({
url: "/Student/CreateStudent",
type: "POST",
dataType: "json",
data: { Prefix: request.term },
success: function(data) {
try {
response($.map(data,
function (item)
{
return { label: item.FirstName, id: item.Id };
}));
} catch (err) {
}
}
});
},
messages:
{
noResults: "jhh", results: "jhjh"
}
});
});
</script>
<script>
$(function () {
$('#addtypevalue').click(function (e) {
var name = $("#StudentName").val();
alert(name);
$('#SelectedNames').
append($("<option></option>").
attr("value", name).
text(name));
$('#hiddensq').append("<input name='UserValues' type='hidden' value='"+ name +"'/>");
});
});
</script>
StudentController.cs
public ActionResult Create()
{
Context.Student student = new Context.Student();
Models.StudentBatch studBatch = new Models.StudentBatch();
studBatch.names = new List<string>();
studBatch.names.Add("Add Student Names");
studBatch.BatchNumberList = student.getBatchList();
return View(studBatch);
}
[HttpPost]
public JsonResult CreateStudent(string Prefix)
{
CreateUser user = new CreateUser();
string stdid = "f14570f0-e7a1-4c22-bf69-60ffbeb7e432";
var StudentList1 = user.GetAllUsers().ToList().Where(u => u.FirstName.Contains(Prefix) && u.usertypeid == stdid);
var StudentList = user.GetAllUsers().ToList();
var searchlist = (from student in StudentList1
where student.FirstName.Contains(Prefix)
select student).ToList();
return Json(StudentList1, JsonRequestBehavior.AllowGet);
}
// POST: Student/Create
[HttpPost]
public ActionResult Create(Models.StudentBatch student, IEnumerable<string> UserValues)
{
try
{
// TODO: Add insert logic here
return RedirectToAction("Index");
}
catch
{
return View();
}
}
If I understood correctly the problem here is passing multiple IDs from a listbox to a POST? One possible way is to assign viewbag like thus in your controller:
ViewBag.StudentList = new SelectList(db.StudentBatch, "studentId", "StudentName");
I use entities to access my models, I think you have a little bit different approach but the point is to give a collection to the Selectlist. Then you specify the data value field and the data text field.
Then in your view, note that it's not ListBoxFor, as it's dynamic:
#Html.ListBox("StudentList", null)
Then finally to be able to receive the values in the POST add the following parameter to your action and you should be able to iterate through it:
string[] StudentList
Finally managed to get the related from the listbox. I followed the instruction mentioned in a particular question. That's how i did.
$("#StudentName").autocomplete({
source: function (request, response) {
$.ajax({
cache: false,
// async: false, NEVER do this
url: '#Url.Action("CreateStudent", "Student")', // don't hard code your url's
data: { Prefix: request.term }, // change
dataType: "json",
type: "POST",
// contentType: "application/json; charset=utf-8", delete
success: function (data) {
response($.map(data, function (item) {
return {
label: item.label,
id: item.id
}
}));
}
})
},select: function(event, ui) {
$.ajax({
cache: false,
type: "POST",
url: '#Url.Action("GetDetails", "Student")',
data: { id: ui.item.id },
success: function (data) {
var name = $("#StudentName").val();
$('#SelectedNames').
append($("<option></option>").
attr("value", ui.item.id).
text(name));
$('#hiddensq').append("<input name='UserValues' type='hidden' value='" + ui.item.id + "'/>");
}
});
}
});
</script>
and in the controller class
[HttpPost]
public JsonResult GetDetails(string id)
{
ViewBag.Value = id;
return Json(ViewBag.Value, JsonRequestBehavior.AllowGet);
}
I have a controller with an Index action which returns a ViewModel and a GetCategories action which should return a partial view.
So here is my CategoryController.cs file:
public class CategoryController : Controller
{
public ActionResult Index()
{
CategoryViewModel ob = new CategoryViewModel();
ob.LoadLanguages();
return View(ob);
}
public ActionResult GetCategories(int langID)
{
CategoryViewModel ol = new CategoryViewModel();
ol.LoadCategoriesByLanguage(langID);
if (Request.IsAjaxRequest())
return PartialView("GetCategories",ol);
In my Index.cshtml view I create a dropdown list and, when the user selects an element, it makes an Ajax request to the getCategories action and on success I should load the GetCategories partial view. The problem is that it redirects me to a new page and I can no longer see my dropdown.
Here is my Index.cshtml file:
#model Onion.Web.ViewModels.CategoryViewModel
<script>
$(document).ready(function () {
$("#ddlLanguages").change(function () {
$.ajax({
type: 'GET',
url: '#Url.Action("GetCategories")' + '?langId=' + this.value,
data: {},
success: callbackFuntion('#Url.Action("GetCategories")' + '?langId=' + this.value),
error: function () { alert('Error'); }
});
});
});
function callbackFuntion(url){
window.location = url;
}
</script>
#Html.DropDownList("Languages", new SelectList(Model.lstLanguages, "LanguageID", "Name"), "SELCT LANGUAGE----->",new { id = "ddlLanguages" })
}
And here is my Category.cshtml file:
#model Onion.Web.ViewModels.CategoryViewModel
<table>
<tr>
<td>ID</td>
<td>Title</td>
</tr>
#foreach (var item in Model.lstCategoryLanguages)
{
<tr>
<td>#item.Title</td>
<td>#item.ShortDescription</td>
</tr>
}
</table>
I can't beleve how easy it is in web forms and here i'm struggling for hours. Is there a better way to do all this. Thank you in advance
I slightly modified your Models and made it working prototype, from here you can get the concept and apply it to your models -
Models -
public class CategoryViewModel
{
public List<string> DDLItems { get; set; }
}
public class CategoryNewViewModel
{
public string Name { get; set; }
}
Controller -
public class MyPartialController : Controller
{
public ActionResult Index()
{
CategoryViewModel ob = new CategoryViewModel();
ob.DDLItems = new List<string>();
ob.DDLItems.Add("1");
ob.DDLItems.Add("2");
ob.DDLItems.Add("3");
return View(ob);
}
public ActionResult GetCategories(int langID)
{
CategoryNewViewModel ol = new CategoryNewViewModel();
if (langID == 1)
ol.Name = "One";
else if (langID == 2)
ol.Name = "two";
else
ol.Name = "three";
return PartialView("GetCategories", ol);
}
}
Index View -
#model MVC.Controllers.CategoryViewModel
#{
ViewBag.Title = "Index";
}
<script src="~/Scripts/jquery-1.10.2.min.js"></script>
<script>
$(document).ready(function () {
$("#DDLCategories").change(function () {
$.ajax({
type: 'GET',
url: '#Url.Action("GetCategories")',
data: {langID : $('#DDLCategories').val()},
success: function (result) { $('#container').html(result); },
error: function () { alert('Error'); }
});
});
});
</script>
<h2>Index</h2>
#Html.DropDownList("DDLCategories", new SelectList(Model.DDLItems), "--Choose any Item--")
<div id="container"> </div>
GetCategories Partial View -
#model MVC.Controllers.CategoryNewViewModel
#Model.Name
When you select a item in Dropdownlist, then the corresponding partialview will be loaded in the div.
Output -
It's normal because you execute a redirection in your success callback.
You can use load function of jQuery to load your partial view in a div of your dom.
<div id="categoriesPlace"></div>
<script>
$(document).ready(function () {
$("#ddlLanguages").change(function () {
$("#categoriesPlace").load('#Url.Action("GetCategories")' + '?langId=' + this.value, function( response, status, xhr ) {
if ( status == "error" ) {
var msg = "Sorry but there was an error: ";
alert( msg + xhr.status + " " + xhr.statusText );
}
}
});
});
</script>
Here's my code (question found below):
VIEW
// This function is called by another function when radioButtonGroup.change().
var requestValues = function (form) {
var option = form.find("input:radio:checked").attr("value");
// This seemingly shows the correct url for the action method desired.
alert("Form Action: " + form[0].action + "\nForm Method: " + form[0].method);
if (form.valid()) {
$.ajax({
url: form[0].action,
type: form[0].method,
data: option,
success: function (result) {
alert("Had success.");
$('#createForm').replaceWith(result);
},
error: function (xhr) {
alert("An error occurred: " + xhr.status + " " + xhr.statusText);
}
});
}
return false;
}
...(other code here)...
#using (Html.BeginForm("CreateForm", "MyController", FormMethod.Post,
new { #id = "optionForm" }))
{
<div id="options">
#foreach (MyOption op in Model.GetOptions()) {
<div class="editor-field">
#Html.RadioButton("formOption", op.OptionType, false,
new { #id = op.ID, #title = #op.Description })
<label for="#op.ID">#op.Name</label>
</div>
}
</div>
<input type="submit" value="Select" style="display:none;" />
}
CONTROLLER
[HttpPost]
public PartialViewResult CreateForm(MyOptionType formOption) {
MyViewModel model = new MyViewModel();
model.ApplyOptionValues(formOption);
return PartialView("_CreateForm", model);
}
REGISTER ROUTES
// Default
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
);
My issue is that when I click a radio button, the AJAX request executes but I get a "404 Not Found" error (even though the alert in the jQuery function seems to show the appropriate url). I spent all day yesterday on this, and I cannot figure out what the heck is wrong. I'm running ASP.NET MVC 3 app on IIS Express, and I'm not using Areas (that I know of anyway). Anyone have any suggestions on how to fix this? Thanks.
EDIT
The alert box shows the following message:
Form Action: https://localhost:44300/MyController/CreateForm
Form Method: post
EDIT
Here is an entire test view and test controller that recreates the error:
VIEW
<h2>TestAction</h2>
<script type="text/javascript">
$(document).ready(function () {
$("#optionForm input[name='radioOption']").change(function () {
requestValues($(this).closest("form"));
});
var requestValues = function (form) {
var option = form.find("input:radio:checked").attr("value");
alert("Form Action: " + form[0].action + "\nForm Method: " + form[0].method);
if (form.valid()) {
$.ajax({
url: form[0].action,
type: form[0].method,
data: option,
success: function (result) {
alert("AJAX success.");
//$('#createForm').replaceWith(result);
},
error: function (xhr) {
alert("An error occurred: " + xhr.status + " " + xhr.statusText);
}
});
}
return false;
}
});
</script>
#using (Html.BeginForm("CreateForm", "Test", FormMethod.Post, new { #id = "optionForm" })) {
#Html.RadioButton("radioOption", "value1", false, new { #id = "radioButton1" })
<label for="radioButton1">Radio Button 1</label>
#Html.RadioButton("radioOption", "value2", false, new { #id = "radioButton2" })
<label for="radioButton2">Radio Button 2</label>
#Html.RadioButton("radioOption", "value3", false, new { #id = "radioButton3" })
<label for="radioButton3">Radio Button 3</label>
<input type="submit" value="Select" style="display:none;" />
}
<div id="createForm"></div>
CONTROLLER
public class TestController : Controller {
public ActionResult TestAction() {
return View();
}
[HttpPost]
public ActionResult CreateForm(string option) {
return View("TestAction");
}
}
#using (Html.BeginForm("CreateForm", "MyController", FormMethod.Post, new { id = "optionForm" }))
should be:
#using (Html.BeginForm("CreateForm", "My", FormMethod.Post, new { id = "optionForm" }))
Remember that in ASP.NET MVC helpers you should not pass the Controller suffix. It is assumed.
So the correct url should be:
https://localhost:44300/My/CreateForm
and not:
https://localhost:44300/MyController/CreateForm
where you obviously have the MyController class:
public class MyController: Controller
{
public ActionResult CreateForm(MyOptionType formOption)
{
...
}
}
In my html I have
<h2>Title goes here</h2>
#using (Html.BeginForm("Action", "Controller", FormMethod.Post, new { id = "myFormID" })) {
<input type="text" id="testinput" name="testinput" />
<input type="text" id="testinput2" name="testinput2" />
<input type="button" value="click me" onclick="submitForm();" />
}
in my js I have
function submitForm() {
dataString = $("#myFormID").serialize();
alert(dataString);
$.ajax({
type: "POST",
url: "/Controller/Action",
data: dataString,
cache: false,
dataType: "json",
success: function (data) {
alert('success!');
},
error: function (XMLHttpRequest, textStatus, errorThrown) {
alert(XMLHttpRequest + "<br />" + textStatus + "<br />" + errorThrown);
}
});
}
In my controller file I have:
public ActionResult Action()
{
return View();
}
[HttpPost]
public ActionResult Action(string testinput, string testinput2)
{
return View();
}
When clicked on "click me" button, I get the following error:
"parsererrorInvalid JSON: "
What am I doing wrong? I am simply trying to pass form data to jquery .ajax.
The alert statement outpust "testinput=gdfgf&testinput2=gfgfd" which is the correct values I entered. SO the error seems to be when serializing....
I am using MVC 3 with razor...I had the impression that passing data between model/view and javascript code was made easier.
I am almost positive that has nothing to do with the data you pass to the $.ajax call and everything with the data returned by /Controller/Action. Open up Fiddler and examine the response. it is likely malformed (or not JSON at all).
if your method accepts only int id as parameter, then dataString should be declared as
var dataString = { id: $("#myFormID").val() };
if you need to pass id and testinput as parameters, then use
var dataString = { id: $("#myFormID").val(), testinput: $("#testinput").val() };
The parameters and names in dataString mutch match the parameters of your action method.