I am not sure what I am doing wrong here.
I have a list where I am creating hyperlinks. I need to point the user to the right page first though so I do a getJson.
I have the following code in my .cshtm file:
$.getJSON('/Home/GetLocType', { "locId": loc.locId },
function(result) {
result = Json.stringify(result);
if(result == '1')
{
$('<li><a id=' + loc.locId + ' href="/DataEntry" rel="external">' + loc.locName + '</a></li>').appendTo("#btnList");
}
else
{
$('<li><a id=' + loc.locId + ' href="/DataEntry/PForm" rel="external">' + loc.locName + '</a></li>').appendTo("#btnList");
}
});
I have the following code in the controller:
private JsonResult GetLocType(int locId)
{
int locationId = Convert.ToInt32(locId);
var result = db.Locations.Where(a => a.LocID == locationId).Select(a => a.TypeId);
return Json(result);
}
The problem I am facing is that the Json method never gets called.
Your controller method is declared as private - As such it would not be accessible.
Change it to public.
Secondly, you should activate allow get - Details on why this is not set by default see - Why is JsonRequestBehavior needed?
public JsonResult GetLocType(int locId)
{
int locationId = Convert.ToInt32(locId);
var result = db.Locations.Where(a => a.LocID == locationId).Select(a => a.TypeId);
return Json(result, JsonRequestBehavior.AllowGet);
}
Related
This is my logic to prevent duplicate values in the controller
public ActionResult ProviderType_Create([DataSourceRequest] DataSourceRequest request, [Bind(Prefix = "models")]IEnumerable<ProviderTypeMasterViewModel> ProviderTypeMasterList)
{
var results = new List<ProviderTypeMasterViewModel>();
try
{
_logger.LogInformation("ProviderTypeMastersController ProviderType_Create Start");
foreach (var ProviderTypeMaster in ProviderTypeMasterList)
{
TblProviderTypeMaster ptm = new ProviderTypeMasterViewModel().ToModel(ProviderTypeMaster);
var provd = _context.TblProviderTypeMasters.Where(p => p.ProviderTypeName == ProviderTypeMaster.ProviderTypeName).ToList();
if (provd != null && provd.Count() == 0)
{
if (ProviderTypeMasterList != null && ModelState.IsValid)
{
string userID = GetUserID();
providerTypeMasterService.SaveProviderTypeMaster(ProviderTypeMaster, userID);
}
}
else
{
duplicate = true;
return this.Json(new DataSourceResult
{
Errors = "my custom error"
});
}
}
_logger.LogInformation("ProviderTypeMastersController ProviderType_Create Complete");
}
catch (Exception e)
{
_logger.LogError("ProviderTypeMastersController ProviderType_Create Failed - " + e.Message);
}
return Json(results.ToDataSourceResult(request, ModelState));
}
I show the error in an alert message using the error event of the kendo grid in my view. Now I need help on these two things.
1.) Is there any other way I could show the error message without an alert message. Like a label? If so where should I hide the label after the duplicate is removed?
2.) I want to highlight the particular value of the grid in which the user has entered the duplicate value. A change like changing the particular grid value to red when id is duplicate and remove the red color when the user changes the duplicate value to a unique value.
I am a beginner and I am stuck here. Can anyone help me with this? Thanks
Just add your error to ModelState:
public JsonResult Create([DataSourceRequest] DataSourceRequest request, [Bind(Prefix = "models")]IEnumerable<ProviderTypeMasterViewModel> ProviderTypeMasterList)
{
if (ModelState.IsValid)
{
foreach (var ProviderTypeMaster in ProviderTypeMasterList)
{
TblProviderTypeMaster ptm = new ProviderTypeMasterViewModel().ToModel(ProviderTypeMaster);
if (_context.TblProviderTypeMasters.Any(p => p.ProviderTypeName == ProviderTypeMaster.ProviderTypeName))
{
ModelState.AddModelError("ProviderTypeName", "ProviderType already exists");
}
else
{
if (ProviderTypeMasterList != null)
{
string userID = GetUserID();
providerTypeMasterService.SaveProviderTypeMaster(ProviderTypeMaster, userID);
}
}
}
}
}
return Json(results.ToDataSourceResult(request, ModelState));
In order to format Kendo Grid Column value with conditionally chosen action you can use one of the suitable examples below. For more information: How Do I Have Conditional Logic in a Column Client Template?.
UI for Javascript:
{
field: "EmployeeName", type: "string", width: "55px", title: "Employee Name",
template: "#= GetEditTemplate(data) #"
}
UI for MVC:
...
columns.Bound(t => t.EmployeeName).Title("Status Name").Template(#<text></text>)
.ClientTemplate("#= GetEditTemplate(data)#").Width("55px");
...
Here is the method used in the example:
<script>
//Change the color of the cell value according to the given condition
function GetEditTemplate(data) {
var html;
if (data.StatusID == 1) {
html = kendo.format(
//"<a class=\"k-button\" href='" + '#Url.Action("Edit1", "Controller")' + "/{0}" + " '>Edit</a> ",
"<span class='text-success'>" +
data.EmployeeName
+ "</span>"
);
}
else {
html = kendo.format(
//"<a class=\"k-button\" href='" + '#Url.Action("Edit2", "Controller")' + "/{0}" + " '>Edit</a> ",
"<span class='text-danger'>Cancel</span>"
);
}
return html;
}
</script>
I'm writing a web application in .Net Core Framework and certain elements of the front end use Ajax calls to API that returns certain data.
If I'm on a page that requires 1 API call, it works fine, however as soon as I get on a page that makes more than 1 calls, debugging (well, going line by line in the code) becomes hell with the debugger jumping up and down the code) and in the end the results all end up as errors.
Rarely will I get the results if a website makes more calls, sometimes it happens but odds of that are.. 1 / 50 and this is unacceptable.
Weirdly enough, after I visit such page and then go back to a page that makes 1 call, even that 1 call ends with an error.
I'm not really sure what I need to include here as a code so I'll add both jquery and the action.
Before I put any code here, I'd like to explain my question..
I'd like to know what exactly is causing this, and why are the ajax calls causing parallel executions of the Action and how could I force that ajax calls are ran one by one or do anything else to fix this issue. I believe at most 30,40 calls should be made by some Views and if even 2 cause such issues, there's obviously a problem here, but unfortunately I'm not skilled enough yet to see and fix it.
Any help will be greatly appreciated.
jquery (I've removed pieces of code simply because they aren't relevant. it's just some class changes):
$(window).ready(function () {
$('.price').each(function (i, e) {
var id = $(e).data('skinid');
var exterior = $(e).data('exterior');
var type = $(e).data('type');
$.ajax({
type: "GET",
url: "/Skin/GetPrice",
data: { Id: id, Exterior : exterior, Type : type },
cache: false,
dataType: "json",
}).complete(function (data) {
var price = data.responseJSON.price;
if (data.responseJSON.querySuccessful)
{
if (data.responseJSON.listingExists)
{
//do stuff here
}
else
{
//other stuff here
}
}
else
{
//print error..
}
});
});
});
Action is quite long so I'll short it up as well:
[HttpGet]
public async Task<ActionResult> GetPrice(int Id = 0, string Exterior = null, string Type = null)
{
PriceViewModel model = null;
if (_context.Skins.Any(x => x.Id == Id))
{
if (Type == "Skin")
{
Skin Query = _context.Skins.Where(x => x.Id == Id).Include(x => x.Weapon).Include(x => x.Quality).Select(x => x).Single();
using (var client = new HttpClient())
{
try
{
string uri = "/market/priceoverview/?currency=3&appid=730&market_hash_name=" + Query.Weapon.Name.Replace(" ", "%20") + "%20|%20" + Query.Name.Replace(" ", "%20") + "%20(" + Exterior.Replace(" ", "%20") + ")";
client.BaseAddress = new Uri("http://steamcommunity.com");
var response = await client.GetAsync(uri);
response.EnsureSuccessStatusCode(); // Throw in not success
var stringResponse = await response.Content.ReadAsStringAsync();
JObject data = JObject.Parse(stringResponse);
if (data["success"].Value<bool>())
{
if (data["lowest_price"] != null)
{
// return good model
}
//return no result model
}
}
catch
{
// return error
}
}
}
if (Type == "Skin-List")
{
Skin Query = _context.Skins.Where(x => x.Id == Id).Include(x => x.Weapon).Include(x => x.Quality).Select(x => x).Single();
Dictionary<Exterior, PriceViewModel> PossibleExteriors = new Dictionary<Exterior, PriceViewModel>();
bool possible = false;
foreach (Exterior e in _context.Exteriors)
{
if (e.Name == Query.BestExterior)
possible = true;
if (possible)
PossibleExteriors.Add(e, null);
if (e.Name == Query.WorstExterior)
possible = false;
}
List<Exterior> exteriors = PossibleExteriors.Keys.ToList();
foreach (Exterior e in exteriors)
{
using (var client = new HttpClient())
{
try
{
client.BaseAddress = new Uri("http://steamcommunity.com");
string uri = "/market/priceoverview/?currency=3&appid=730&market_hash_name=" + Query.Weapon.Name.Replace(" ", "%20") + "%20|%20" + Query.Name.Replace(" ", "%20") + "%20(" + e.Name.Replace(" ", "%20") + ")";
var response = await client.GetAsync(uri);
response.EnsureSuccessStatusCode(); // Throw in not success
var stringResponse = await response.Content.ReadAsStringAsync();
JObject data = JObject.Parse(stringResponse);
if (data["success"].Value<bool>())
{
if (data["lowest_price"] != null)
{
model = new PriceViewModel
{
QuerySuccessful = true,
ListingExists = true,
ListingUrl = "http://steamcommunity.com/market/listings/730/" + Query.Weapon.Name + " | " + Query.Name + " (" + e.Name.Replace(" ", "%20") + ")",
Price = data["lowest_price"].ToString()
};
PossibleExteriors[e] = model;
}
else
{
model = new PriceViewModel
{
QuerySuccessful = true,
ListingExists = false,
ListingUrl = "http://steamcommunity.com/market/listings/730/" + Query.Weapon.Name + " | " + Query.Name + " (" + e.Name.Replace(" ", "%20") + ")",
Price = ""
};
PossibleExteriors[e] = model;
}
}
}
catch
{
model = new PriceViewModel
{
QuerySuccessful = false,
ListingExists = false,
Price = ""
};
PossibleExteriors[e] = null;
}
}
}
if (PossibleExteriors.Values.Any(x => x != null))
{
//return good model
}
else
{
//return empty
}
}
}
//return error
}
I'd like to know what exactly is causing this, and why are the ajax calls causing parallel executions of the Action and how could I force that ajax calls are ran one by one or do anything else to fix this issue.
You've got a fundamental misunderstanding about asynchronous calls. This JavaScript will fire off a request, then continue into the next iteration of the loop before getting a response. The complete function will be called whenever an asynchronous call is completed, whenever that happens and in whatever order it happens in. This means that new calls are arriving faster than the application can return results, so it's working on more than one request at a time. Perfectly normal!
If these calls need to be made in a specific order, why not lump them all into one request? Pass a list of items into the data property and do a loop in C#.
If this has to be a loop in JavaScript, you'll need to wait for a response from the asynchronous call (basically make it synchronous) If you want to do this calls synchronously, as in call GetPrice, get a response, do something with the response, then go to the next iteration and repeat, you'll need to change the approach.
var $prices = $('.prices').map(function() {
return new { Id: id, Exterior : exterior, Type : type }
});
getPrice($prices, 0);
function getPrice(prices, index) {
$.ajax({
type: "GET",
url: "/Skin/GetPrice",
data: prices[index] // if this were the whole prices list, you could do the loop in C# instead
cache: false,
dataType: "json",
}).complete(function (data) {
// do all that processing stuff
index++;
// if there are more prices to compute, call the function again
if (prices.length - 1 >= index) {
getPrice(prices, index);
}
});
}
I'm receiving JSON data from this method:
function CallAPI(controllerName, functionName, sendData, callback) {
var ajax = new XMLHttpRequest();
ajax.onreadystatechange = function () {
if (ajax.readyState == 4) {
if (ajax.status == 200) {
var response = JSON.parse(ajax.responseText);
callback(response);
}
else {
callback();
}
}
}
ajax.open("POST", "http://" + window.location.host + "/API/" + controllerName + "/" + functionName, true);
ajax.setRequestHeader('Content-Type', 'application/json');
ajax.send(JSON.stringify(sendData));
}
function someRequest() {
var data = {};
data.userID = 1;
data.someValue = 20;
CallAPI("Home", "Add", data, function (response) {
if(response) {
alert(response.Message); //This property always exist
}
else {
alert("internet/connection error.");
}
});
}
And my Controller is:
[System.Web.Http.HttpPost]
public HttpResponseMessage Add(int userID, int someValue)
{
//Here!
return Request.CreateResponse(HttpStatusCode.OK, new GenericResponseAPI() { Status = false, Message = "Generic Message." });
}
I can create a model and MVC would bind it accordingly, but I have so many of these requests that I don't want to create various models (or a big one containing all of the properties), but instead have these simple functions with basic type parameters like this.
What do I need to do to be able to work with the controller function above, without changing the content-type of the incoming message?
Edit: I found a workaround with this:
[System.Web.Http.HttpPost]
public HttpResponseMessage Add(JObject jObject)
{
int userID = (int)jObject.getValue("userID").ToObject(typeof(Int32));
int someValue = (int)jObject.getValue("someValue").ToObject(typeof(Int32));
return Request.CreateResponse(HttpStatusCode.OK);
}
I imagine the reason is that your function signature is:
function CallAPI(controllerName, functionName, sendData, callback)
and you're calling
CallAPI("Home", "Add", function (response) { ... })
So you're never actually sending data in the format MVC is expecting.
I'd double check this by using something like Fiddler and by debugging your JavaScript code using your browsers dev-tools.
I have a problem. I'm trying to redirect my application using a controller method, like this:
[HttpPost]
public ActionResult GetSelected(string Selected, string NewRoleID)
{
var StringSelected = Selected.Split(',');
for (var i = 0; i < StringSelected.Count(); i++)
{
if (StringSelected[i] == "true")
{
R_ROLEMENU newMenu = new R_ROLEMENU();
newMenu.RoleID = int.Parse(NewRoleID);
newMenu.MenuID = i + 1;
var existing = (from item in db.RoleMenus
where (item.RoleID == newMenu.RoleID && item.MenuID == newMenu.MenuID)
select item).ToArray();
if (existing.Count() == 0)
{
db.RoleMenus.Add(newMenu);
db.SaveChanges();
}
}
else
{
R_ROLEMENU oldMenu = new R_ROLEMENU();
oldMenu.RoleID = int.Parse(NewRoleID);
oldMenu.MenuID = i + 1;
var existing = (from item in db.RoleMenus
where (item.RoleID == oldMenu.RoleID && item.MenuID == oldMenu.MenuID)
select item).ToArray();
if (existing.Count() != 0)
{
db.RoleMenus.Remove(existing[0]);
db.SaveChanges();
}
}
}
return RedirectToAction("Logout", "Home");
}
And I'm calling the method with jquery, like this:
$.post("/m_menu/getselected?selected=" + selectedmenus + "&newroleid=" + roleid, function () {
//todo
});
The problem is, the application keeps redirected to index page instead of the Logout action in Home Controller. What am I doing wrong? The rest of the code within the controller is running fine, it's just the redirection that's not working. Please help, thank you
As it is an ajax call RedirectToAction will simply return the action called view as response of post you have to redirect via jquery in $.post call back function:
In Action instead of:
return RedirectToAction("Logout", "Home");
do:
return Content(Url.Action("Logout", "Home"));
and in call back of $.post do this:
$.post("/m_menu/getselected?selected=" + selectedmenus + "&newroleid=" + roleid, function (response) {
window.location = response;
});
or call call javascript at the end of action:
var script = "window.loaction ='"+Url.Action("Logout","Home")+"' ;";
return JavaScript(script);
Not sure why, everything seems formatted fine, but I get the HTTP 404 error when attempting to access a function in my controller. Here's the aspx:
function CheckIfPacked() {
if ($("#OrderNumber").val() != "") {
var url = "/Packing/PackageTracking/CheckIfPacked";
$.ajax({
url: url,
cache: false,
data: "orderNumber=" + $("#OrderNumber").val() + "&actionyes=GetSalesOrder()",
success: function (data) {
var domElement = $(data);
if (data != "") {
$('#MessageDiv').append(domElement);
}
});
}
}
And here's the controller:
public Result CheckIfPacked(string orderNumber) {
var mesEntity = new MESEntities();
var packh = from packhead in mesEntity.Packing_Transaction_Headers
where packhead.Order_No_ == orderNumber
select packhead.Completed_by_Packer;
if (packh.First() == 0)
{
return new Result { Success = true, Message = string.Format("You have not finished packing order {0}, are you sure you want to navigate away from this page?", orderNumber) };
}
else
{
return null;
}
}
I think I've just stared at this too long. Thanks.
your method should be static and you should use webmethod attribute for your function :
[WebMethod]
public static Result CheckIfPacked(string orderNumber) {
var mesEntity = new MESEntities();
var packh = from packhead in mesEntity.Packing_Transaction_Headers
where packhead.Order_No_ == orderNumber
select packhead.Completed_by_Packer;
if (packh.First() == 0)
{
return new Result { Success = true, Message = string.Format("You have not finished packing order {0}, are you sure you want to navigate away from this page?", orderNumber) };
}
else
{
return null;
}
}