I am writing a function on a webpage where when you type in a serial number, it will look up what model of part goes with that serial number in a SQL database. Right now, the JsonResult is working and finding the correct information, but something is wrong with the jquery and ajax because it is not showing up after you click off of the serial number box (set with a blur, which does trigger as well).
Here is the controller code.
public JsonResult SerialNumberSearch(string serialnum)
{
var result = db.IASerialNoMasters.Where(x => x.SerialNo == serialnum).Select(x => x.Model).Single().ToString();
return Json(result, JsonRequestBehavior.AllowGet);
}
Here is the script that I currently have on my View.
<script type="text/javascript">
var serialnum;
var url = '#Url.Action("SerialNumberSearch", "WarrantyRegistration")'
$("#SerialNum").blur(function () {
GetLiftModel();
});
function GetLiftModel() {
serialnum = $("#SerialNum").val();
$.ajax({
type: "GET",
url: url,
data: { serialnum: serialnum },
success: function(data) {
$('#ModelName').val(data.Model);
}
})
}
</script>
And this is the code for the textboxes on the View.
<div class="row">
#Html.TextBoxFor(model => model.SerialNum, new { placeholder = "Serial #" })
#Html.ValidationMessageFor(model => model.SerialNum, null, new { #class = "text-danger" })
</div>
<br />
<div class="column-1">
#Html.TextBoxFor(model => model.ModelName, new { placeholder = "Model" })
#Html.ValidationMessageFor(model => model.ModelName, null, new { #class = "text-danger" })
</div>
Can anyone tell what I am missing from the function GetLiftModel area of the code?
Are you sure you want to show data.Model? In case you return JsonResult then data variable is in fact representation of your serial numbers and so it's probably that data.Model is in fact undefined.
Try change it to
$.ajax({
type: "GET",
url: url,
data: { serialnum: serialnum },
success: function(data) {
$('#ModelName').val(data);
}
})
on the other hand based on fact you are returning just string there is no reason to return JsonResult. You could change signature of your controller method to
public JsonResult SerialNumberSearch(string serialnum)
{
var result = db.IASerialNoMasters
.Where(x => x.SerialNo == serialnum)
.Select(x => x.Model).Single().ToString();
return result;
}
This ultimately depends on what you want to access and if you need to access multiple properties :
Need a single property? If you only need a single property, then you should be able to isolate that property out similar to your current code and only pass that back.
Need multiple properties? Then you'll likely need to return the entire object or at least part of it from your SerialNumberSearch() method.
Returning a Single Property
Your current code has a final ToString() call that seems to indicate that you'll be returning just a single property, in this case the Model property :
var result = db.IASerialNoMasters
.Where(x => x.SerialNo == serialnum)
.Select(x => x.Model)
.Single()
.ToString(); // This returns a string
Since that is the case, your data object that is being returned will already contain that specific property, and thus you'll just need to use data as seen below :
success: function(data) {
// data will already contain your result, so just use it
$('#ModelName').val(data);
}
Returning Multiple Properties or an Object Graph
If you expect to be able to access multiple properties from your object in JSON, you'll want to actually return the object itself and let the serializer handle passing it to Javascript so that it can be used as expected :
public JsonResult SerialNumberSearch(string serialnum)
{
var result = db.IASerialNoMasters
.SingleOrDefault(x => x.SerialNo == serialnum);;
if(result == null)
{
// Do something if it doesn't exist
return HttpNotFound();
}
return Json(result, JsonRequestBehavior.AllowGet);
}
And then simply access the property you need from your data object within your Javascript code :
success: function(data) {
// data will already contain your result, so just use it
$('#ModelName').val(data.Model);
}
Related
I want to get the last ID from a database table and increment by 1, to be displayed in an Input or Label parameter of HTML.
Most tutorials display it in tables. Here is my code:
index.cshtml
<td>Trans Id</td>
<td><input id="tbTransID" type="text" /></td>
<script>
$(document).ready(function () {
$.ajax({
type: "GET",
url: "/CashAdvance/GetTransID",
data: "{}",
success: function (data) {
var s = data.TransID;
}$("#tbTransId").html(s);
}
});
});
</script>
CashAdvanceController
public ActionResult GetTransID()
{
AcctgContext db = new AcctgContext();
return Json(db.CATransactions.Select(x => new
{
TransID= x.TransID + 1
}).ToList(), JsonRequestBehavior.AllowGet);
}
You need to change your linq query in the controller as below:
public ActionResult GetTransID()
{
AcctgContext db = new AcctgContext();
return Json(db.CATransactions.OrderByDescending(i => i.TransID).Select(i=>new
{
TransID= x.TransID + 1
}).FirstOrDefault(), JsonRequestBehavior.AllowGet);
}
In your query, you are selecting list of values whereas you need only the max id to increment it.
I try to pass 'regular' parameters type from an ajax call ($.post) from a view to a controller which is supposed to receive those parameters plus a List>.
I need this List cause those parameters will be different from model.types, and the method in the controller dispatch all params in a switch case to private methods.
I tried several jquery objects builds, JSON.stringify, the array with indexes in the string (I know I can't name columns explicitly... part of my question) which always ends in the List> to null in the backend method.
The 'params' are visible in xhr debug, but the parameter _options is always null (ref controller method).
Here is my vars and my ajax call :
function initDocumentsPreviewsActions() {
$('.documents-list-preview-action').on('click', function () {
if (xhrPreviewLoad != undefined)
xhrPreviewLoad.abort();
$('#documents-preview').html('<div class="general-form-message-loader"></div>');
documentCurrentIndex = $(this).data('btnindex');
setDatatableRowActive();
var documentType = $(this).data('documenttype');
var adherentRessourceId = $(this).data('adherentressourceid');
var annee = $(this).data('annee');
var echeancier = $(this).data('echeancier');
var destinataireid = $(this).data('destinataireid');
var destinatairetypeid = $(this).data('destinatairetypeid');
var emetteurid = $(this).data('emetteurid');
var emetteurmandatid = $(this).data('emetteurmandatid');
var trimestres = $(this).data('trimestres');
var params = [
{ '_annee': '' + annee + '', '_echeancier': '' + echeancier + '', '_trimestres': '' + trimestres + '' }
];
xhrPreviewLoad = $.ajax({
url: '/Documents/PreviewDocumentSingle',
data: {
_documentType: documentType,
_adherentRessourceId: adherentRessourceId,
_annee: annee,
_destinataireId: destinataireid,
_destinataireType: destinatairetypeid,
_emetteurId: emetteurid,
_emetteurMandatId: emetteurmandatid,
_echeancier: echeancier,
_options: JSON.stringify(params)
},
dataType: 'json',
type: 'POST'
}).done(function (documentPartialView) {
$('#documents-preview').html('<img src="' + documentPartialView.src + '"/>');
xhrPreviewLoad = undefined;
});
});
}
xhd Parameters in Firefox debugger :
_documentType AppelCotisation
_adherentRessourceId 836
_annee 2018
_destinataireId 11
_destinataireType Syndicat
_emetteurId 16289
_emetteurMandatId 5986
_echeancier False
_options [{"_annee":"2018","_echeancier":"False","_trimestres":"undefined"}]
Controller method :
[HttpPost]
public JsonResult PreviewDocumentSingle(string _documentType, int _adherentRessourceId, int _destinataireId, string _destinataireType, int _emetteurId, int _emetteurMandatId, List<KeyValuePair<string, string>> _options)
{
//(_options = null)
//some code
return JsonResult
}
I already have done this a long time ago but I cannot put a hand or my brain on it. I'm sure it's a little thing.
I expect to get ALL my parameters correctly or being suggested to declare another List of a different type in the backend (and how to formalize it in front), or Array... well... any help is good to come.
But I'd really like to keep mus ctor in the backend as it is.
I finally findout myself how to solve this simple problem by changing to a Dictionnaray instead of a List> in my controller's method parameters and build a simple js object like this :
var options = {};
options['_annee'] = annee;
options['_echeancier'] = echeancier;
options['_trimestres'] = trimestres;
I am running into some trouble with my ajax call. Here is the controller code:
[Route("RatingInfo/HandleRequest")]
[HttpPost]
public ActionResult HandleRequest(Dictionary<string, string> textBoxValues)
{
var result = CreateJson(textBoxValues); // This is a simplified example
return Json(result);
}
And here is my Jquery/ajax (Razor syntax):
function PassData () {
var data = {};
$('.divCell input').each(function (index, item) {
var id = $(item).attr('id');
var value = item.value;
data['dictionary[' + index + '].Key'] = id;
data['dictionary[' + index + '].Value'] = value;
});
$.ajax({
url: '#Url.Action("HandleRequest")',
type: 'POST',
dataType: 'JSON',
traditional: true,
data: data,
sucesss: function (result) {
alert('Success');
}
})
}
The idea here is to get the data from each textbox and pass it back to the server as a Dictionary with the id as the key and value as, well, the value.
Stepping through the Chrome debugger, the JS data object is built successfully.
From the debugger:
Local
data: Object
dictionary[0].Key: "Address"
dictionary[0].Value: "123 Main St"
dictionary[1].Key: "ZipCode"
dictionary[1].Value: "99999"
dictionary[2].Key: "Phone1"
dictionary[2].Value: "(555) 555-5555"
...
__proto__: Object
However, when the data is passed back to the controller, the values inside textBoxValues does not contain the passed data. Rather, it contains two key/value pairs with keys controller and action and values the names of the controller and action.
From the Visual Studio debugger:
textBoxValues = Count = 2
[0] = {[controller, RatingInfo]}
[1] = {[action, HandleRequest]}
How can I get Jquery to pass the data rather than the controller/action names? I am confused as to how this can even happen in the first place. Any help would be appreciated.
UPDATE
Sorry, I had put wrong code in.
The reason why this was not working is because the name of the parameter was incorrect, giving you a mismatch.
The below will work for you. Notice the name of dictionary is changed to your parameter textBoxValues:
function PassData() {
var data = {};
$('.divCell input').each(function (index, item) {
var id = $(item).attr('id');
var value = item.value;
data['textBoxValues[' + index + '].Key'] = id;
data['textBoxValues[' + index + '].Value'] = value;
});
$.ajax({
url: '#Url.Action("HandleRequest")',
type: 'POST',
traditional: true,
data: data,
sucesss: function (result) {
alert('Success');
}
})
}
I am trying to make 2 cascading drop down lists.
First one works fine, you pick an item but when you go to the second drop down list, you can actually see correct number of spaces generating according to the items in the database but not the items themselves!
Its like they are invisible!
Can you please advise?
My View :
#using (Html.BeginForm("Browse", "Bookings", new { id = "TypeItemFormID", data_itemsListAction = #Url.Action("ItemsList") }))
{
<fieldset>
<legend> Type/Item</legend>
#Html.DropDownList("department", ViewBag.ItemTypesList as SelectList, "Select a Type", new {id="ItemTypeID"})
<div id="ItemsDivId">
<label for="Items">Items </label>
<select id="ItemsID" name="Items"></select>
</div>
<p>
<input type ="submit" value="Submit" id="SubmitID" />
</p>
</fieldset>
}
<script type="text/javascript">
$('#ItemTypeID').on('change', function () {
$.ajax({
type: 'POST',
url: '#Url.Action("GetItemTypeForm")',
data: { itemTypeId: $('#ItemTypeID').val() },
success: function (results) {
var options = $('#ItemsID');
options.empty();
options.append($('<option />').val(null).text("- Select an Item -"));
$.each(results, function () {
options.append($('<option />').val(this.ItemsID).text(this.Value));
});
}
});
});
</script>
My Controller :
[HttpPost]
public JsonResult GetItemTypeForm(string itemTypeId)
{
//pseudo code
var data = from s in db.Items
where s.ItemType.ItemTypeName == itemTypeId
select s.ItemName;
return Json(data);
}
You have the initial problem I mentioned in my comment, but it appears from your comments that your member names probably do not match either.
This may not be exact, as we do not know all your data/member names, but you may want something like this (using an anonymous type to return the shape of data you expect):
[HttpPost]
public JsonResult GetItemTypeForm(string itemTypeId)
{
//pseudo code
var data = from s in db.Items
where s.ItemType.ItemTypeName == itemTypeId
select new { Value = s.ItemName, ItemsID = s.ItemId };
return Json(data);
}
Im asp.net mvc3 c# code returns json list like this:
return Json(new { name = UserNames, imageUrl = ImageUrls });
UserNames and ImageUrls are both List<string> types
And this is my javascript
function StartSearch(text) {
$.ajax({
url: '/Shared/Search',
type: 'POST',
data: { SearchText: text },
dataType: 'json',
success: function (result) {
$.each(result, function (i, item) {
alert(result[i].name);
});
}
});
}
How I can get names and ImageUrls?
Thanks
Access name as a property of result like this result.name[i]
Essentially, result will contain name and imageUrl which are both arrays, just like you have defined in your anonymous type, so your code should be modified like this to display an alert for each name in the name array
function StartSearch(text) {
$.ajax({
url: '/Shared/Search',
type: 'POST',
data: { SearchText: text },
dataType: 'json',
success: function (result) {
$.each(result.name, function (i, item) {
alert(item);
});
}
});
}
as $each iterates over the items in the name array, it will pass the item to the second parameter of your call back, i.e. item.
so
$.each(result.name, function (i, item) {
alert(item);
});
will popup each name.
Notes:
You may want to change the properties on your anonymous type to reflect that they are a collection:
return Json(new { UserNames = UserNames, ImageUrls = ImageUrls });
this way it will make more sense when you iterate over them in your success function.
As AlfalfaStrange pointed out, I didn't demonstrate how you might access both arrays. Which made me think, what is the relationship between user names and image urls?
Is this a list of images for a user? Maybe what you should consider is creating a specific model for this. For instance, UserDisplayModel:
public class UserDisplayModel
{
public string UserName {get;set;}
public string ImageUrl {get;set;}
}
In your controller return a list of UserDisplayModels. If this is the case, you'll have to rethink why they are two separate lists in the first place. Maybe ImageUrl should be a field on the User table.
So now, when you're returning a single list, e.g.
List<UserDisplayModel> users = //get users from db
return Json(new { Users = Users});
you can iterate them in one go in js code:
$.each(result.Users, function (i, item) {
alert(item.Name);
alert(item.ImageUrl);
});
This alerts the value of Name from each record of each list.
$.each(result, function (i, item) {
for (var x = 0; x < result.FirstList.length; x++) {
alert(result.FirstList[x].Name);
alert(result.SecondList[x].Name);
}
});
This assumes your Json response if formed correctly. Like this:
return Json(new { FirstList = results, SecondList = otherResults }, JsonRequestBehavior.AllowGet);
But as a side note, I see other problems with your code that you need to address
You're actually not performing a POST, you're searching based on input. Change POST to GET in your Ajax call
Change your action return line to allow for the get and make sure your are returning a JsonResult.
Naming conventions for C# method parameters call for Pascal-casing. Use a lowercase letter for first character
public JsonResult Search(string searchText) {
....
return Json(new { name = UserNames, imageUrl = ImageUrls }, JsonRequestBehavior.AllowGet);
}