Post data to MVC controller from DropDownList - javascript

I have a MVC, multiple select DropDownList that populates the Select Items from a SelectListItem model.
#Html.DropDownList("EmployeeStatuses", (IEnumerable<SelectListItem>)ViewBag.EmployeeStatuses, new { multiple = "multiple", style = "width: 100%;", #class = "select2", onchange = "UpdateEmployeeStatusFilter()", id = "employee-status-type" })
When the user selects or unselects items from the DropDownList, I want to run a method in my controller that will filter the data in the view. This is done with the onChange event UpdateEmployeeStatusFilter().
<script type="text/javascript">
function UpdateEmployeeStatusFilter() {
var value = $('#employee-status-type').val();
console.log(value);
var a = ["X", "Y", "Z"];
console.log(a);
$.ajax({
type: 'POST',
url: '#Url.Action("SearchEmployee", "Employee")',
data: { valueMember: value },
dataType: 'json',
traditional: true,
success: function (msg) { alert(msg) }
});
};
</script>
When I debug the script, I am able to get the value of value and write that to the console window. When the controller method is called, the value is null.
public IActionResult SearchEmployee(string itemsSelected)
{
// Do Stuff with itemsSelected
return RedirectToAction("Index");
}
My question is how do I get that value into my controller?
I am not sure if this code is relevant or not, but I will include it for clarity.
public IActionResult Index()
{
// Get Employment Statuses
IEnumerable<SelectListItem> statuses = _mockDataRepository.GetEmployeeStatuses().Select(c => new SelectListItem
{
Value = c.ValueMember,
Text = c.DisplayMember,
Selected = c.ValueMember == "AC"
});
ViewBag.EmployeeStatuses = statuses;
}
public class SelectListItem
{
[Key]
public string ValueMember { get; set; }
public string DisplayMember { get; set; }
public int SortOrder { get; set; } = 0;
}

Name mismatch. The SearchEmployee() action method has itemsSelected input parameter. Therefore set the same parameter name in the .ajax call:
data: { itemsSelected: value },

Related

Posting JSON object via AJAX to ASP.NET Core Web API

I have tried different methods that have been posted on this site, but nothing seems to work.
I want to create a clothing site (a personal project). The products on the site have their own class, that is built like this:
public class Product
{
public string ProductName { get; set; }
public string ProductPrice { get; set; }
public int Quantity { get; set; }
}
The shopping cart is another class that will contain a list of Product objects and this one is built like this:
public class ShoppingCart
{
[Key]
public int Id { get; set; }
List<Product> ProductList { get; set; }
public string ClientName { get; set; }
public string ClientAddress { get; set; }
public string ClientMail { get; set; }
}
I created an API Controller class and thought that would solve the problem. It looks like this:
[Route("api/Shopping")]
[ApiController]
public class ShoppingCartController : ControllerBase
{
[HttpPost]
public ShoppingCart Save([FromBody] ShoppingCart s)
{
return s;
}
}
In my JavaScript code I create my JSON object and try to post it like this:
var orderB = document.getElementById("orderB");
orderB.addEventListener("click", function () {
var inputName = document.getElementById("inputName").value;
var inputAddress = document.getElementById("inputAddress").value;
var inputMail = document.getElementById("inputMail").value;
var auxArray = [];
for (var i = 0; i < productsAux.length; i++) {
auxArray[i] = { "productName": productsAux[i].titlu, "productPrice": productsAux[i].pret, "quantity": localStorage.getItem(productsAux[i].titlu)};
}
var shoppingCart = {
productList: auxArray,
clientName: inputName,
clientAddress: inputAddress,
clientMail: inputMail
};
$.ajax({
type: "POST",
data: JSON.stringify(shoppingCart),
url: "api/shopping/save",
contentType: "application/json charset=utf-8",
}).done(function (res) {
alert(res);
});
After I push the order button on my page I expect to see the alert pop-up with the callback result which I suppose is the ShoppingCart object that is created using the JSON that I send.
For those coming on later, I would suggest checking that your types are correct on both ends. For instance, if your JS is posting a byte array and C# tries to convert it to an int, the whole object (not just that prop) will be null.
This has caught me many a time.
I opened the Network tab and I got this: I got a 404 (kind of
expected that) , the name of the method 'save' , a type of 'xhr' and a
size of 45B.
The 404 error obviously means the url/routing is wrong. Here to solve it ,you have two ways to achieve.
First way:
You can change url to "api/shopping" in ajax as follow:
$.ajax({
type: "POST",
data: JSON.stringify(shoppingCart),
url: "api/shopping",
contentType: "application/json charset=utf-8",
}).done(function (res) {
alert(res);
})
Second way:
You can change the path name
of Save action by Attribute routing with Http verb attributes as follow:
[Route("api/Shopping")]
[ApiController]
public class ShoppingCartController : ControllerBase
{
[HttpPost("Save")]
public ShoppingCart Save([FromBody] ShoppingCart s)
{
return s;
}
}
Update
According to your comment, in addition to the above updates, you also need to modify the routing settings as follows:
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
});
Debug result:

Posting Data in Asp.NET MVC 5 app with JavaScript & ViewModel

The basic problem is this. I'm using CKEditor for an interface for a blog post of sorts. CKEditor gets the wordcount, but I have to use some client-side JavaScript to clean it up. I want to pass the wordcount into the database so I know how many words each post has.
I have a viewmodel for the post:
public class NewStoryViewModel
{
[Required]
public string Title { get; set; }
[Required]
public string Content { get; set; }
[Required]
public int Genre { get; set; }
public IEnumerable<Genre> Genres { get; set; }
[Required]
public int StoryType { get; set; }
public IEnumerable<StoryType> StoryTypes { get; set; }
public int WordCount { get; set; }
[Required]
public int StoryAgeRange { get; set; }
public IEnumerable<StoryAgeRange> StoryAgeRanges { get; set; }
[Required]
public int Visibility { get; set; }
public IEnumerable<Visibility> Visibilities { get; set; }
}
And the controller for the post:
[Authorize]
[HttpPost]
[ValidateAntiForgeryToken]
[ValidateInput(false)]
public ActionResult New (NewStoryViewModel viewModel)
{
//confirm form data is valid
if (ModelState.IsValid)
{
//create new story object
var newStory = new Story
{
AuthorId = User.Identity.GetUserId(),
Title = viewModel.Title,
Content = viewModel.Content,
GenreId = viewModel.Genre,
StoryTypeId = viewModel.StoryType,
StoryAgeRangeId = viewModel.StoryAgeRange,
VisibilityId = viewModel.Visibility,
CreatedAt = DateTime.Now,
WordCount = viewModel.WordCount
};
//add new story to db
dbContext.Stories.Add(newStory);
//save db
dbContext.SaveChanges();
return RedirectToAction("Index", "Story");
}
else
{
return View(viewModel);
}
}
On the client-side in the razor view, I have this:
$(document).ready(function () {
$('#addStoryBtn').on('click', function () {
//get the content of the div
var wordcount = $('#cke_wordcount_Content').html();
//chop off the words before the number in the string
var slicedWordCount = wordcount.slice(6);
//remove any excess white space
var trimmedWordCount = slicedWordCount.trim();
//capture the index of the slash
var indexOfSlash = trimmedWordCount.indexOf("/");
//split the string at the slash to get the words used out of the total allotted
var finalWordCount = trimmedWordCount.slice(0, indexOfSlash);
//$.ajax({
// url: "/story/new",
// type: 'POST',
// data: {
// WordCount = finalWordCount
// },
// success: function (data) {
// console.log("Success")
// },
// error: function (error) {
// console.log("error is " + error);
// }
//})
});
});
I do this because CKEditor prints the word count out of the maximum like this:
Words: 4/5000
so I use a bit of JS to remove everything I don't need and keep the number before the slash.
But the ajax post didn't work (stepping through the controller, it returns 0).
I thought about using a hiddenfield in the view. Something like:
#Html.Hidden(new { WordCount = finalWordCount })
But the razor view gives me an error that finalWordCount doesn't mean anything in the current context. I surmise it's because finalWordCount is subject to the button click and since the addPost button hasn't been clicked, finalWordCount is undefined.
Any suggestions on how to pass the wordcount to the viewmodel?
You've mentioned in the comments that you're experiencing a 500 internal server error, which I'm guessing is after you've tried Shyju's suggestion to fix the invalid JSON. My guess is you're unable to even debug the controller action right now because it's expecting an anti-forgery token to be passed to it, but you're not sending that in the body of the POST request.
To fix that, try this:
var form = // selector for your form
var token = $('input[name="__RequestVerificationToken"]', form).val();
$.ajax({
url: "/story/new",
type: 'POST',
data: {
__RequestVerificationToken: token,
WordCount: finalWordCount
},
success: function (data) {
console.log("Success")
},
error: function (error) {
console.log("error is " + error);
}
});
That should hopefully fix the validation error, allowing you to at least reach the action.
The MVC application is probably expecting a json format request body, as
that is the default configuration of asp.net MVC.
So before posting the data to the server you need to stringify the model to a proper json.
Try it like this
var data = JSON.stringify({WordCount: finalWordCount});
$.ajax({
url: "/story/new",
type: 'POST',
data: data,
success: function (data) {
console.log("Success")
},
error: function (error) {
console.log("error is " + error);
}
})

How to pass in nested data from the client to the controller

I have a form that has two sections. 3 input fields and another section with 10 checkboxes.
public class Customerproductdto
{
public string CustomerNumber { get; set; }
public string CustomerName { get; set; }
public string CustomerPhone { get; set; }
List<ProductDetails> GetAllChecked {get;set;}
}
public class ProductDetails
{
public string ProductName{ get; set; }
}
Here is jquery code I am using to get all the values of the checkboxes that were
checked on my form. They are about 10 and users could check everything.
var yourArray[]
$("input:checkbox[name=type]:checked").each(function(){
yourArray.push($(this).val());
});
Here is javascript that I use to collect the data and pass to my controller.
How can I pass in my array here all in one shot?
var objdata =
({
CustomerNumber: txtcustnumber,
CustomerName: txtcustname,
CustomerPhone: txtphone
//How do I pass the yourArray here?
});
var url = "#Url.Action("WriteToDb", "Home")";
var completeData = JSON.stringify({ 'Information': objdata });
$.get(url, { 'objdata': completeData }, function (data) {
$('#mainListContent').html(data);
});
Please note that I will like to deserialize this once I get to the controller.
Here is the method.
public ActionResult WriteToDb(string objdata)
{
Customerproductdto getAllTaskSaved = null;
try
{
var stripOffObjectName = JObject.Parse(objdata)["Information"];
var cleanedData = JsonConvert.DeserializeObject<Customerproductdto>(stripOffObjectName.ToString());
getAllTaskSaved = _dtcDataService.WriteTaskToDb(cleanedData, "Add");
}
catch (Exception ex)
{
logger.Error(ex);
}
return PartialView("_Taskdisplay", getAllTaskSaved);
}

how to assign values to nested object through json object array

This is my model class:
public class SearchForFlight
{
public SearchForFlight()
{
Segments = new otherType();
}
public int AdultCount { get; set; }
public JourneyType JourneyType { get; set; }
public string Sources { get; set; }
public otherType Segments { get; set; }
}
public class otherType
{
public string Origin { get; set; }
public string Destination { get; set; }
public FlightCabinClass FlightCabinClass { get; set;}
public DateTime PreferredDepartureTime { get; set;
public DateTime PreferredArrivalTime { get; set; }
}
Now, My requirement is to post objects along with nested object to an external api.
The required form is something like this:
{
AdultCount: $("#AdultCount").val(),
JourneyType: $("#JourneyType :selected").text(),
PreferredAirlines: null,
Segments: [
{
Origin: $("#Origin").val(),
Destination: $("#Destination").val(),
FlightCabinClass: $("#FlightCabinClass").val(),
PreferredDepartureTime:$("#PreferredDepartureTime").val(),
PreferredArrivalTime: $("#PreferredArrivalTime").val(),
}
]
}
So, i have created another class OtherType and put all those nested objects into it.
I got the idea from this so question
How to send nested json object to mvc controller using ajax
Now, this is my Script tag with all the code inside to post simple objects along with nested objects.But nested objects value comes out to be null.
How should i model this code here.
<script>
$(document).ready(function () {
$("#btnPost").click(function () {
var sof = {
AdultCount: $("#AdultCount").val(),
JourneyType: $("#JourneyType :selected").text(),
PreferredAirlines: null,
Segments: [
{
Origin: $("#Origin").val(),
Destination: $("#Destination").val(),
FlightCabinClass: $("#FlightCabinClass").val(),
PreferredDepartureTime: $("#PreferredDepartureTime").val(),
PreferredArrivalTime: $("#PreferredArrivalTime").val(),
}
],
};
$.ajax(
{
url: "/api/Flight/SearchFlight",
type: "Post",
data: sof,
success: function (data) {
alert(data);
}
});
});
});
</script>
Posted Properties values for Origin, Destination comes out to be null.
The textbox rendered on view page are something like this:
#Html.TextBoxFor(model => model.Segments.Origin)
Any hint please.
Remove the array [] for Segments. Use contentType and stringify in your $.ajax func. Use the generated id for the Origin. It might not be "Origin". So,pls change it accordingly.
<script>
$(document).ready(function () {
$("#btnPost").click(function () {
var sof = {
AdultCount: $("#AdultCount").val(),
JourneyType: $("#JourneyType :selected").text(),
PreferredAirlines: null,
Segments: {
Origin: $("#Origin").val(),
Destination: $("#Destination").val(),
FlightCabinClass: $("#FlightCabinClass").val(),
PreferredDepartureTime: $("#PreferredDepartureTime").val(),
PreferredArrivalTime: $("#PreferredArrivalTime").val(),
},
};
$.ajax(
{
url: "/api/Flight/SearchFlight",
type: "Post",
contentType: 'application/json',
data: JSON.stringify(sof),
success: function (data) {
alert(data);
}
});
});
});
</script>

How to pass File type value to controller using javascript

I have input type file control in view and I would like to send selected attached file to controller.
But the value is always null for file parameter in Controller action as shown below.
Please let me how to send file details to controller using ajax.
View:
<div>
#Html.DropDownListFor(model => model.IDdocument, IdList, new { id = "ddlFileType" })
#Html.TextBoxFor(model => model.Description, new { id = "txtDescription" })
#Html.TextBoxFor(model => model.Attachment, new { type = "file", id="txtFile" })
#Html.ActionLink("Add", "", "ESignature", new { }, new { id = "lnkAddAttachment" })
</div>
JavaScript:
$("#lnkAddAttachment").click(function (e) {
var fileType = document.getElementById("ddlFileType").value;
var desc = document.getElementById("txtDescription").value;
var selectedFile = document.getElementById('txtFile').files[0];
var url = '#Url.Content("~/")' + "ESignature/AddAttachment?type=" + fileType + "&desc=" + desc + "&file=" + selectedFile;
$.ajax({
url: url,
data: $('#frmRegistration').serialize(),
type: 'GET',
success: function () {
var url = '#Url.Content("~/")' + "ESignature/Registration"
$('#gridAttachments').load(url+' #gridAttachments')
}
});
return false;
})
Controller:
[HttpGet]
public ActionResult AddAttachment(BRUser brUser, string type, string desc, HttpPostedFileBase file)
{
// Here I am getting all values except for file parameter
}
Model:
public class BRUser
{
public string IDdocument { get; set; }
public string Description { get; set; }
public HttpPostedFileBase Attachment { get; set; }
}

Categories

Resources