Invalid JSON issue with asp.net jquery ajax call
Hi,
I am facing a strange issue while receiving response for an ajax call when I fire it to page.
I am using jquery to post data to the code behind
Javascript -
var jsonData = { "a": JSON.stringify(obj1),"b": JSON.stringify(obj2)};
jsonData = JSON.stringify(jsonData);
$.ajax({
type: "POST",
contentType: "application/json; charset=utf-8",
url: 'Page.aspx/AjaxCall',
async: true, cache: true, data: jsonData, dataType: "json",
success: function (msg) {
alert('hurray! Success. ' + msg.d);
},
error: function (xhr, textstatus, errorThrown) {
alert('there was an error' + errorThrown);
}
});
C#
[WebMethod]
public static string AjaxCall(string a, string b)
{
Dictionary<object, Dictionary<string, object>> x = new Dictionary<object, Dictionary<string, object>>();
Dictionary<string, object> z = new Dictionary<string, object>();
Dictionary<object, object> y = new Dictionary<object, object>();
int u = 0;
int v = 0;
// deserialise z class
try
{
if (!string.IsNullOrEmpty(b))
{
z = (Dictionary<string, object>)new JavaScriptSerializer().Deserialize(b, typeof(Dictionary<string, object>));
if (z.ContainsKey("IsProctored"))
y.Add("BlurCount", z["BlurCount"]);
if (z.ContainsKey("IsCrossClicked"))
{
y.Add("IsCrossClicked", z["IsCrossClicked"]);
}
}
}
catch (InvalidOperationException ioe)
{
throw new Exception();
}
// deserialise items class
try
{
x = (Dictionary<object, Dictionary<string, object>>)
new JavaScriptSerializer().Deserialize(a, typeof(Dictionary<object, Dictionary<string, object>>));
}
catch (InvalidOperationException ioe)
{
throw new Exception();
}
if (u == 0)
{
throw new Exception();
}
if (v == 0)
{
throw new Exception();
}
if (x.Count == 0)
{
//throw new Exception();
}
try
{
// saves the data in backend
SaveResponse(u, v, x, y);
}
catch (Exception ex)
{
throw new Exception();
}
return "response fired";
}
The error that I get is 'Invalid JSON' (in Firebug's response tab of ajax call). Although it's straightforward ajax call.
I am kinda confused why this maay be happening because this it works on majority of the cases and fails on some other.
Any idea would be a great help.
thanks!
You have lots of throw Exception statements in there.
Any of those would trigger the invalid Json response!
You need to trap error messages and instead of throwing an exception, return some valid Json to indicate the problem.
Also for debugging I suggest using Firefox with HttpFox installed - you can then analyze the exact content of any responses, whether by Ajax or not. I find it an invaluable and free tool for situations like this.
It was because of some strange issue with Firefox 3.6. I restarted the browser and tested it again and things were working as expected.
Related
I am new in ASP.NET MVC Web API. I am trying to modified the return JSon to this format
{
"Error": false,
"Status": 200,
"Response": []
}
Now I able to do that by follow this post https://www.devtrends.co.uk/blog/wrapping-asp.net-web-api-responses-for-consistency-and-to-provide-additional-information . But the problem is I not able to show ModelState error like 'First name is required' because the code only show the first hit error.
if (error != null)
{
content = null;
//only show the first error
errorMessage = error.Message;
}
So I did some modification, now the code is written as below:
if (error != null)
{
content = null;
foreach(var e in error)
{
//if the error's type is ModelState
if (e.Key.Equals("ModelState"))
{
var allErrors = e.Value;
foreach (var modelError in (IEnumerable<KeyValuePair<string, object>>)allErrors)
{
var msg = modelError;
errorMessage = string.Concat(errorMessage, ", ", ((String[]) modelError.Value)[0]);
}
}
else
{
errorMessage = e.Value.ToString();
}
}
}
Now it's able to show all errors but the code is messy. I am writing this questions to find out what is the proper way to write this kind of code.
You can iterate over all the errors and concatenate them using StringBuilder. String.Join is much faster than Append for less than 1000 items (it is unlikely you will have so many errors in the modelstate object):
public static ValidationResult CheckValid(ModelStateDictionary modelState, string httpName = null)
{
if (!modelState.IsValid)
{
var sb = new StringBuilder();
sb.AppendLine(httpName + " failed: Invalid Json:");
foreach (var pair in modelState)
{
var error = String.Join(";", pair.Value.Errors.Select
(
i =>
{
if (!String.IsNullOrEmpty(i.ErrorMessage))
return i.ErrorMessage;
return i.Exception.Message;
}
));
sb.AppendLine($"Property: {pair.Key} Errors: ({error})");
}
return new ValidationResult(false, sb.ToString());
}
else
return new ValidationResult(true, "");
}
I am creating a web server through asp.net.
The source works well in debug mode.
However, after posting to iis, if you go through the source, you will get the error 'HTTP Error 503. The service is unavailable' after about 20 seconds.
I am confident that there is an error in the OpenFileDialog section.
In the past, this code worked well after posting. I do not know what has been modified since then.
Thanks in advance for your help.
.js code
action: function (e, dt, node, config) {
$.ajax({
"url": "/api/Member/ExcelRead",
"type": "POST",
"datatype": 'json',
success: function (data) {
if (data === 'OK') {
alert("성공");
}
},
error: function (response, state, errorCode) {
alert("실패");
}
});
.cs
public class MemberController : ApiController
{
[HttpPost]
public string ExcelRead()
{
ExcelHelper helper = new ExcelHelper();
Thread th = new Thread(helper.ReadExcelData);
th.SetApartmentState(ApartmentState.STA);
th.Start();
th.Join();
if (helper.data == null)
return ("NO");
return ("OK");
}
}
public void ReadExcelData()
{
IsRun = false;
OpenFileDialog openFile = new OpenFileDialog();
openFile.DefaultExt = "xlsx";
openFile.Filter = "Excel Files(*.xlsx)|*.xlsx";
DialogResult dresult = openFile.ShowDialog();
if (dresult != DialogResult.OK)
{
return;
}
if (openFile.FileNames.Length > 0)
{
foreach (string filename in openFile.FileNames)
{
//this.textBox1.Text = filename;
}
}
}
I am using paged lists on my mvc application. I have tons of different pages that do this, but for SOME random reason, this one throws a 400 bad request error. I am almost positive the code is the same.
public ViewResult ManageWeapons(string sortOrder, string currentFilter, string searchString, int? page)
{
ViewBag.CurrentSort = sortOrder;
ViewBag.NameSortParm = String.IsNullOrEmpty(sortOrder) ? "WeaponName_desc" : "";
if (searchString != null)
{
page = 1;
}
else
{
searchString = currentFilter;
}
ViewBag.CurrentFilter = searchString;
var weapon = from s in db.Weapons
select s;
if (!String.IsNullOrEmpty(searchString))
{
weapon = weapon.Where(s => s.WeaponName.Contains(searchString));
}
switch (sortOrder)
{
case "WeaponName_desc":
weapon = weapon.OrderByDescending(s => s.WeaponName);
break;
default: // ascending
weapon = weapon.OrderBy(s => s.WeaponName);
break;
}
int pageSize = 25;
int pageNumber = (page ?? 1);
return View(weapon.ToPagedList(pageNumber, pageSize));
}
I invoke it as so, to sort a column
//This function updates a pagedList using Ajax
function getSorterWeapons(sortOrder, currentFilter) {
//alert($(this).val());
console.log("making it!");
$.ajax({
type: "GET",
url: '#Url.Action("ManageWeapons", "AdminTools")',
cache: false,
data: { sortOrder: sortOrder, currentFilter: currentFilter },
error: function () {
alert("An error occurred.");
},
success: function (data) {
$("#manageWeaponsBox").html(data);
console.log("success!");
alert(data);
}
});
}
I have set breakpoints on the server and it makes it through just fine. Nothing seems to be going wrong, but the client constantly outputs 400 error in console.
I am doing this EXACT same function for other tables in my database and it works fine. This one has me to wits end.
This one would have been rather obvious has it been in an HTML post. The problem is as simple as that I had an error in the view (from accidently adding a character). The c# function was executing fine and then the code was breaking in the view side, one of the pitfalls of debugging using ajax and mvc.
im have a weird problem whereby my functionality of exporting to excel doesnt seem to work.
im using J-Query and AJAX to pass html data to a http handler which has some simple context.Response code which all seems fine. Anyway, heres my code:
// my hyperlink for user to click
Click Here to Export
my J-Query/AJAX code
<script type="text/javascript">
$(document).ready(function () {
$("#hyperLink").click(function (e) {
var result = $('#output').html();
var newRes = result.replace('\n', '');
$.ajax({
url: "ExportToExcelhandler.ashx",
data: { 'htmlData': newRes },
dataType: "json",
type: "POST",
success: function (data) {
alert(data);
}
});
});
});
</script>
and my handler:
public void ProcessRequest(HttpContext context)
{
string htmlStuff = context.Request["htmlData"];
string trimStart = "";
string trimEnd = "";
if (htmlStuff != null)
{
trimStart = htmlStuff.Substring(75, htmlStuff.Length - 75);
trimEnd = trimStart.Remove(trimStart.Length - 8, 8) + "";
}
string final= trimEnd;
context.Response.Clear();
context.Response.Buffer = true;
context.Response.AddHeader("content-disposition", "attachment; filename=excelData.xls");
context.Response.ContentType = "application/vnd.ms-excel";
HttpResponse response = context.Response;
context.Response.Output.Write(finalHtmlData);
context.Response.Flush();
context.Response.End();
}
-- Granted, I'm doing some weird things with replace function in my J-Query, and Substring and Remove in my handler; this is because i had to trim my html data so that only the table with the data inside it was included (caused error otherwise). The html data is just report data. So the html data is passed fine to the handler, and it goes through the ProcessRequest method fine, yet doesn't export to excel. Any help would be greatly appreciated, thanks.
Split this into two HTTP handlers, one to generate the Excel data and the second to retrieve the data and have a resource point at it, like this:
GenerateExcelDocument HTTP handler code:
public void ProcessRequest(HttpContext context)
{
string htmlStuff = context.Request["htmlData"];
var docIdentifier = this.GenerateExcelDocument(htmlStuff);
context.Response.ContentType = "text/plain";
context.Response.Write(docIdentifier.ToString("N"));
}
private Guid GenerateExcelDocument()
{
var identifier = Guid.NewGuid();
string trimStart = "";
string trimEnd = "";
if (htmlStuff != null)
{
trimStart = htmlStuff.Substring(75, htmlStuff.Length - 75);
trimEnd = trimStart.Remove(trimStart.Length - 8, 8) + "";
}
// Logic that generates your document and saves it using the identifier
// Can save to database, file system, etc.
return identifier;
}
Now you can call this HTTP handler, like this:
$(document).ready(function () {
$("#hyperLink").click(function (e) {
var result = $('#output').html();
var newRes = result.replace('\n', '');
$.ajax({
url: "GenerateExcelDocument.ashx",
data: { 'htmlData': newRes },
dataType: "json",
type: "POST",
success: function (result) {
window.location.href = '/RetrieveExcelDocument.ashx/' + result;
}
});
});
});
Note: The success callback is where you can hook up the HTML resource to the file retrieval from the server (think href of the anchor tag that worked without passing data to the handler before).
Finally, we need to build the retrieval HTTP handler logic to actually get the Excel document, based upon the identifier returned from the GenerateExcelDocument HTTP handler call, like this:
RetrieveExcelDocument HTTP handler code:
public void ProcessRequest(HttpContext context)
{
var identifier = new Guid(context.Request.Url.Segments[1]);
// Get Excel document content from database, file system, etc. here
var fileContent = GetExcelDocument(identifier);
context.Response.AddHeader("content-disposition",
"attachment; filename=excelData.xls");
context.Response.ContentType = "application/vnd.ms-excel";
context.Response.OutputStream.Write(fileContent, 0, fileContent.Length);
}
i want to generate the table of contents from database.. using jquery ajax in asp.net, i am using sql server 2008 as a backend. for this i created a webmethod in my normal aspx page. and on the clientside wrote the ajax script to fetch records but when i loop through the results, i gets message undefined and nothing happens.. i want to generate table out of the records from database below is my webmethod.
[WebMethod]
public static Poll[] GetPollDetailed()
{
SqlConnection con = new SqlConnection(ConfigurationManager.ConnectionStrings["SiteSqlServer"].ConnectionString);
SqlDataAdapter da = new SqlDataAdapter("sp_SelectQuestion", con);
da.SelectCommand.CommandType = CommandType.StoredProcedure;
da.SelectCommand.Parameters.AddWithValue("#siteid", 3);
DataTable dt = new DataTable();
da.Fill(dt);
List<Poll> _poll1 = new List<Poll>();
foreach (DataRow row in dt.Rows)
{
Poll _poll = new Poll();
_poll.QuestionID = Convert.ToInt32(row["questionID"]);
_poll.Question = row["question"].ToString();
_poll.Published = Convert.ToInt32(row["visible"]);
_poll.Date = Convert.ToDateTime(row["Added_Date"]);
}
return _poll1.ToArray();
}
public class Poll
{
public Poll() { }
private int _questionId, _published;
private string _question;
private DateTime _date;
public int QuestionID
{
get { return _questionId; }
set { _questionId = value; }
}
public string Question
{
get { return _question; }
set { _question = value; }
}
public DateTime Date
{
get { return _date; }
set { _date = value; }
}
public int Published
{
get { return _published; }
set { _published = value; }
}
}
</code>
and below is my script.
<code>
$(this).load(function () {
$.ajax({
type: "POST",
url: "AddPollAJax.aspx/GetPollDetailed",
data: "{}",
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function (data) {
for (i = 0; i < data.length; i++) {
alert(data[i].QuestionID);
}
},
error: function (data) {
alert("Error: " + data.responseText);
}
});
});
</code>
can any one please help me to resolve this issue, i am very curious about it.
Assuming your service is configured correctly to return JSON data, issue lies at your js code fragment for success callback i.e.
success: function (data) {
for (i = 0; i < data.length; i++) {
alert(data[i].QuestionID);
}
},
MS ASP.NET script services always return a wrapped JSON due to security issues, so you need unwrap resultant JS object to get the actual data. So you need to change the code to
success: function (result) {
var data = result.d; // actual response will be in this property
for (i = 0; i < data.length; i++) {
alert(data[i].QuestionID);
}
},
BTW, ASP.NET Web Services are now considered legacy, so I will suggest you to migrate to WCF services instead.