Unexpected token in JSON - c#

I have checked JSON string response of at
https://jsonformatter.curiousconcept.com/ and it says that JSON string is valid.
Following is the function which I have used to serialize data to JSON string:
private string getJSONData()
{
obj_userSession = new UserSession();
DataTable dtRender = null;
DataView dvRender = null;
obj_userSession = new UserSession();
if (obj_userSession.LoginData != null && obj_userSession.EmailsDetails != null)
{
dvRender = new DataView(obj_userSession.EmailsDetails);
dtRender = dvRender.ToTable("EmailsDetails", false, "MessageDate", "SentFrom", "MessageBody", "SentTo", "MLSNumber");
return JsonConvert.SerializeObject(dtRender);
}
return "";
}
And here is the response from above function as JSON string:
[
{
"MessageDate": "2016-04-04T05:42:38.273",
"SentFrom": "Site Team",
"MessageBody": "<html>\r\n<head>\r\n\t<style type=\"text/css\">\r\n\t\t.c0 { font-family:'Arial';font-size:10.5pt; }\r\n\t\t.c1 { margin-left:0pt;margin-top:0pt;margin-right:0pt;margin-bottom:7.5pt; }\r\n\t</style>\r\n</head>\r\n<body class=\"c0\">\r\n<p class=\"c1\">Hi Joe, </p>\r\n<p class=\"c1\">Testing Site</p>\r\n<p class=\"c1\">--James</p>\r\n<p class=\"c1\"></p>\r\n</body>\r\n</html>\r\n",
"SentTo": "James",
"Number": ""
}
]
We does not getting any error in code but result not displayed in browser. And gets above mention error in developer tools in browser.
If I removed MessageBody from function getJSONData to avoid it from serializing and remove binding code from design page for MessageBody then it works fine.
What character I have to escape from MessageBody and how to do it?
Edit
This is AngularJS controller function which I have used to get data from:
$scope.browseListing = function (strURL) {
$scope.getURL(strURL);
$http.post($scope.URL)
.then(function (response) {
$scope.Data = response.data;
if ($scope.IsMap)
$scope.LoadMapData();
if ($scope.IsDetails)
$scope.buildReportURL($scope.Data[0].ListingID);
}, function (response) {
$log.info(response);
});
};
And this is the html binding:
<tr ng-repeat="listing in Data">
<td colspan="6">
<table class="tblListingOuter">
<tr>
<th style="width:20%;">
</th>
<th style="width:80%;">
</th>
</tr>
<tr>
<td><b>Date: </b>{{ listing.MessageDate }}</td>
<td><b>Message: </b></td>
</tr>
<tr>
<td><b>Sent By: </b>{{ listing.SentFrom }}</td>
<td rowspan="3">
<pre contenteditable="true" ng-bind-html="listing.MessageBody | unsafe"></pre>
</td>
</tr>
<tr>
<td><b>Sent To: </b>{{ listing.SentTo }}</td>
</tr>
<tr>
<td><b>MLSNO: </b>{{ listing.MLSNumber }}</td>
</tr>
</table>
</td>
</tr>

In Newtonsoft JsonSerializerSettings you have property StringEscapeHandling which specifies how strings are escaped when writing json. code below may work for you
var settings = new JsonSerializerSettings();
settings.StringEscapeHandling = StringEscapeHandling.EscapeHtml;
return JsonConvert.SerializeObject(dtRender, settings)
acceptable values for this property listed in documentation here: http://www.newtonsoft.com/json/help/html/T_Newtonsoft_Json_StringEscapeHandling.htm
you may try other flags to get it working

This is just a guess, but you may try double-escaping the escaped characters in the MessageBody, like this:
[
{
"MessageDate": "2016-04-04T05:42:38.273",
"SentFrom": "Site Team",
"MessageBody": "<html>\\r\\n<head>\\r\\n\\t<style type=\\"text/css\\">\\r\\n\\t\\t.c0 { font-family:'Arial';font-size:10.5pt; }\\r\\n\\t\\t.c1 { margin-left:0pt;margin-top:0pt;margin-right:0pt;margin-bottom:7.5pt; }\\r\\n\\t</style>\\r\\n</head>\\r\\n<body class=\\"c0\\">\\r\\n<p class=\\"c1\"\>Hi Joe, </p>\\r\\n<p class=\\"c1\\">Testing Site</p>\\r\\n<p class=\\"c1\\">--James</p>\\r\\n<p class=\\"c1\\"></p>\\r\\n</body>\\r\\n</html>\\r\\n",
"SentTo": "James",
"Number": ""
}
]

Related

Microsoft Teams Notificaitons CSS Styling

Is there a way to style Teams Notifications?
Posting to a WebHook the following works:
string _html = #"<table width='100%'>
<tr>
<th>Service</th>
<th>2 hours</th>
<th>4 hours</th>
<th>8 hours</th>
<th>24 hours</th>
<th>48 hours</th>
</tr>
<tr style='background-color: #1a1a1a;'>
<td>2343</td>
<td>132</td>
<td>43</td>
<td>12</td>
<td>132</td>
<td>532</td>
</tr>
</table>";
var values = new Dictionary<string, string>{
{"themeColor", "ffd11a"},
{ "title", "My Title" },
{ "textFormat", "markdown" },
{ "text", _html }
};
var json = JsonSerializer.Serialize(values);
var stringContent = new StringContent(json);
var response = await client.PostAsync(webhookUrl, stringContent);
however when I try to add <style> tag it no longer works, and it seems that only 'inline' styles work. Is there a way to add CSS to Teams Notifications Webook?

How to find last column of a table using Html Agility Pack

I have a table like this:
<table border="0" cellpadding="0" cellspacing="0" id="table2">
<tr>
<th>Name
</th>
<th>Age
</th>
</tr>
<tr>
<td>Mario
</td>
<th>Age: 78
</td>
</tr>
<tr>
<td>Jane
</td>
<td>Age: 67
</td>
</tr>
<tr>
<td>James
</td>
<th>Age: 92
</td>
</tr>
</table>
I want to get the last td from all rows using Html Agility Pack.
Here is my C# code so far:
await page.GoToAsync(NumOfSaleItems, new NavigationOptions
{
WaitUntil = new WaitUntilNavigation[] { WaitUntilNavigation.DOMContentLoaded }
});
var html4 = page.GetContentAsync().GetAwaiter().GetResult();
var htmlDoc4 = new HtmlDocument();
htmlDoc4.LoadHtml(html4);
var SelectTable = htmlDoc4.DocumentNode.SelectNodes("/html/body/div[2]/div/div/div/table[2]/tbody/tr/td[1]/div[3]/div[2]/div/table[2]/tbody/tr/td[4]");
if (SelectTable.Count == 0)
{
continue;
}
else
{
foreach (HtmlNode row in SelectTable)//
{
string value = row.InnerText;
value = value.ToString();
var firstSpaceIndex = value.IndexOf(" ");
var firstString = value.Substring(0, firstSpaceIndex);
LastSellingDates.Add(firstString);
}
}
How can I get only the last column of the table?
I think the XPath you want is: //table[#id='table2']//tr/td[last()].
//table[#id='table2'] finds the table by ID anywhere in the document. This is preferable to a long brittle path from the root, since a table ID is less likely to change than the rest of the HTML structure.
//tr gets the descendent rows in the table. I'm using two slashes in case there might be an intervening <tbody> element in the actual HTML.
/td[last()] gets the last <td> in each row.
From there you just need to select the InnerText of each <td>.
var tds = htmlDoc.DocumentNode.SelectNodes("//table[#id='table2']//tr/td[last()]");
var values = tds?.Select(td => td.InnerText).ToList() ?? new List<string>();
Working demo here: https://dotnetfiddle.net/7I8yk1

Calling ajax request from asp.net razor view

How do I initiate an ajax request (calling controller action) from razor view which returns the data in JSON format?
At the moment after clicking the action link in my razor view the page does the post request which redirects the page to /actionName which of course does not exist.
I am also using jQuery but not sure how do I fetch the data from razor view which needs to be passed if I use jQuery ajax method.
ShowEventLogs.cshtml
#{ ViewBag.Title = "Event Logs"; }
#model IEnumerable
<Application.Models.EventLogs>
<table id="data-table" class="table display responsive" style="width:100%">
<thead class="thead-colored thead-light">
<tr>
<th>Time</th>
<th>Scheme</th>
<th>Serial Number</th>
<th>Batch</th>
<th>Exp Date</th>
<th>Product Code</th>
<th>Http Code</th>
<th>Is Confirmed?</th>
<th>Confirmation Date</th>
<th>Verify Pack</th>
</tr>
</thead>
<tbody>
#foreach (var item in Model)
{
<tr>
<td>#item.Timestamp</td>
<td>#item.ProductCodeScheme</td>
<td>#item.SerialNumber</td>
<td>#item.Batch</td>
<td>#item.ExpirationDate</td>
<td>#item.ProductCode</td>
<td>#item.HttpResponseCode</td>
<td>#item.ConfirmedParsed</td>
<td>#item.ConfirmedDate</td>
if (#item.HttpResponseCode == "202")
{
<td class="text-secondary">#Html.ActionLink("Verify Pack", "VerifyPack", "Home", new { ProductCodeScheme = #item.ProductCodeScheme, ProductCode = #item.ProductCode, SerialNumber = #item.SerialNumber, Batch = #item.Batch, ExpirationDate = #item.ExpirationDate, CommandStatusCode = 0 }, new { #class = "text-info" })</td>
}
else
{
<td class="text-secondary">Not Available</td>
}
</tr>
}
</tbody>
</table>
}
Controller action
[HttpPost]
public ActionResult VerifyPack(string productCodeScheme, string productCode, string serialNumber, string batch, string expirationDate, int commandStatusCode, string orderTrackingNo = null) {
string TextAreaResult = string.Empty;
string TextAreaResultException = string.Empty;
string TextAreaResultHttpOperationCode = string.Empty;
string TextAreaResultHttpResponseCode = string.Empty;
string TextAreaResultHttpInformation = string.Empty;
string TextAreaResultHttpWarning = string.Empty;
string TextAreaResultState = string.Empty;
string RemoteIpAddress = string.Format("{0}", Request.UserHostAddress);
try {
using(SecureMediDatabase database = new SecureMediDatabase(this)) {
DatabaseFactory.setDatabase(database);
Request baseRequest = (Request) database.createRequest(Country);
ServiceThread serviceThread = new ServiceThread(0, null, Country);
serviceThread.attach(this);
baseRequest.setId(0);
baseRequest.setProductCodeScheme(productCodeScheme);
baseRequest.setRequestType(1); //single pack
baseRequest.setProductCode(productCode);
baseRequest.setSerialNumber(serialNumber);
baseRequest.setBatch(batch);
baseRequest.setExpirationDate(expirationDate);
baseRequest.setWorkstation(RemoteIpAddress);
baseRequest.setManualEntry(string.IsNullOrEmpty(expirationDate) || string.IsNullOrEmpty(batch));
if (baseRequest.isManualEntry()) {
switch (commandStatusCode) {
case 2:
case 3:
break;
default:
throw new NotSupportedException("This operation does not support manual entries!");
}
}
switch (Country) {
case "SE":
SecureMediRequestSE requestSE = (SecureMediRequestSE) baseRequest;
requestSE.setUserId(#User.Identity.Name);
requestSE.setCommandStatusCode(commandStatusCode);
requestSE.OrderTrackingNumber = orderTrackingNo;
break;
case "FI":
SecureMediRequestFI requestFI = (SecureMediRequestFI) baseRequest;
requestFI.setSubUserId(#User.Identity.Name);
break;
}
serviceThread.RunRequest(control, baseRequest, apteekki);
TextAreaResult = string.Format("{0} {1} {2} {3} {4}", baseRequest.getResponseOperationCode(), baseRequest.getHttpResponseCode(), baseRequest.getHttpInformation(), baseRequest.getHttpWarning(), baseRequest.getResponseStatusCode());
TextAreaResultHttpOperationCode = string.Format("{0}", baseRequest.getResponseOperationCode());
TextAreaResultHttpResponseCode = string.Format("{0}", baseRequest.getHttpResponseCode());
TextAreaResultHttpInformation = string.Format("{0}", baseRequest.getHttpInformation());
TextAreaResultHttpWarning = string.Format("{0}", baseRequest.getHttpWarning());
TextAreaResultState = string.Format("{0}", baseRequest.getResponseStatusCode());
}
} catch (Exception exc) {
TextAreaResultException = "Exception: " + exc.Message;
}
return Json(new {
result = TextAreaResult,
httpOperationCode = TextAreaResultHttpOperationCode,
httpResponseCode = TextAreaResultHttpResponseCode,
httpInformation = TextAreaResultHttpInformation,
httpWarning = TextAreaResultHttpWarning,
state = TextAreaResultState,
exception = TextAreaResultException,
isSuccess = TextAreaResultHttpResponseCode == "200" || TextAreaResultHttpResponseCode == "202"
});
}
Error based on the answer:
Basically #Html.ActionLink() helper renders anchor tag (<a>) with attributes and defaulted to use GET request by refreshing whole page, hence you need to add preventDefault() in order to use AJAX callback from that element. If the action method uses HTTP GET method, you can perform simple AJAX call against common class of the anchor link like this:
$('.text-info').on('click', function (e) {
e.preventDefault();
var url = $(this).attr('href');
$.get(url, function (response) {
// do something with AJAX response
});
});
However since target controller action marked as [HttpPost], you need to extract query string parameters from href attribute with additional function and use them in the AJAX call with type: 'POST' setting, or use $.post():
$('.text-info').on('click', function (e) {
e.preventDefault(); // mandatory to prevent GET request
var url = $(this).attr('href');
var pcs = getQueryStringParams(url, 'ProductCodeScheme');
var pc = getQueryStringParams(url, 'ProductCode');
var sn = getQueryStringParams(url, 'SerialNumber');
var batch = getQueryStringParams(url, 'Batch');
var expDate = getQueryStringParams(url, 'ExpirationDate');
var csc = getQueryStringParams(url, 'CommandStatusCode');
// create key-value pair for action method parameters
var obj = { ProductCodeScheme: pcs, ProductCode: pc, SerialNumber: sn, ... }
$.ajax({
type: 'POST',
url: url.split('?')[0], // URL without query string, or use '#Url.Action("VerifyPack", "Home")'
data: obj,
dataType: 'json', // expects response as JSON
success: function (response) {
// do something with AJAX response
},
error: function (xhr, status, err) {
// error handling
}
});
// just make sure that the link is not redirecting
return false;
});
function getQueryStringParams(url, name) {
return (RegExp(name + '=' + '(.+?)(&|$)').exec(url)||[,null])[1];
}
Actually there exists another way to call AJAX from anchor tag like #Ajax.ActionLink(), depending on your choice:
#Ajax.ActionLink("Verify Pack", "VerifyPack", "Home", new { ProductCodeScheme = #item.ProductCodeScheme, ProductCode = #item.ProductCode, SerialNumber = #item.SerialNumber, Batch = #item.Batch, ExpirationDate = #item.ExpirationDate, CommandStatusCode = 0 },
new AjaxOptions { HttpMethod = "POST",
InsertionMode = InsertionMode.Replace,
UpdateTargetId = "targetElementId",
OnComplete = "onComplete();"
},
new { #class = "text-info" })
Note:
If you need to handle AJAX request and normal request from the same controller, you can differentiate them using Request.IsAjaxRequest() (or Context.Request.Headers["X-Requested-With"] == "XMLHttpRequest" in Core MVC).
Something like this should get you started. Add a class to the items you need to pull information from. Then instead of using an actionlink just create a normal a element with a unique class as well. Have JQuery handle click events on those links and pass the other TD items of the same row to the controller via an AJAX call.
$(".button").click( function() {
var tr = $(this).closest("tr");
var ProductCodeScheme = tr.find(".ProductCodeScheme").html();
var SerialNumber = tr.find(".SerialNumber").html();
var Batch = tr.find(".Batch").html();
var ExpirationDate = tr.find(".ExpirationDate").html();
var ProductCode = tr.find(".ProductCode").html();
$.ajax({
url: "/Verify Pack/VerifyPack",
type: "POST",
data: ({
ProductCodeScheme: ProductCodeScheme,
SerialNumber: SerialNumber,
Batch: Batch,
ExpirationDate: ExpirationDate,
ProductCode: ProductCode
}),
cache: false,
success: function(data){
//Do something here for a successful POST
}
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table id="data-table" class="table display responsive" style="width:100%">
<thead class="thead-colored thead-light">
<tr>
<th>Time</th>
<th>Scheme</th>
<th>Serial Number</th>
<th>Batch</th>
<th>Exp Date</th>
<th>Product Code</th>
<th>Http Code</th>
<th>Is Confirmed?</th>
<th>Confirmation Date</th>
<th>Verify Pack</th>
</tr>
</thead>
<tbody>
<tr>
<td>Timestamp 1</td>
<td class="ProductCodeScheme">ProductCodeScheme 1</td>
<td class="SerialNumber">SerialNumber 1</td>
<td class="Batch">Batch 1</td>
<td class="ExpirationDate">ExpirationDate 1</td>
<td class="ProductCode">ProductCode 1</td>
<td>HttpResponseCode 1</td>
<td>ConfirmedParsed 1</td>
<td>ConfirmedDate 1</td>
<td class="text-secondary">Item 1</td>
</tr>
<tr>
<td>Timestamp 2</td>
<td class="ProductCodeScheme">ProductCodeScheme 2</td>
<td class="SerialNumber">SerialNumber 2</td>
<td class="Batch">Batch 2</td>
<td class="ExpirationDate">ExpirationDate2</td>
<td class="ProductCode">ProductCode 2</td>
<td>HttpResponseCode 2</td>
<td>ConfirmedParsed 2</td>
<td>ConfirmedDate 2</td>
<td class="text-secondary">Item 2</td>
</tr>
</tbody>
</table>

Bootstrap table sorting works inconsistently with LINQ

I have a bootstrap datatable in my view in a MVC application. I use the sorting functionality provided to sort it by a column called CreatedOn and load it on the screen.
<div class="container">
<div class="no-more-tables">
<table id="tblTemplate" class="table table-advance dataTable">
<thead>
<tr>
<th style="display:none">
ID
</th>
<th style="width:14%">
Type
</th>
<th style="width:25.5%;">
Subject
</th>
<th style="width:15%;">
Created By
</th>
<th style="width:15%;">
Created on
</th>
</tr>
</thead>
<tbody>
#foreach (var item in Model.lstBoxes)
{
<tr>
<td class="text-left" style="display:none">#item.Id</td>
<td class="text-left">#item.Type</td>
<td class="text-left">#item.Subject</td>
<td class="text-left">#item.CreatedBy</td>
<td class="text-left">#item.CreatedOn</td>
</tr>
}
</tbody>
</table>
</div>
</div>
The sorting functionality script on load:
function initialSortCommon(tblName,colNo) {
$("#tblTemplate").dataTable(
{
"bDestroy": true
}
).fnDestroy();
$(document).ready(function () {
$("#tblTemplate").dataTable({
"bDestroy": true,
"aaSorting": [[4, 'desc']],
"oLanguage":
{
"sSearch": "Search all columns:",
},
});
});
}
The issue is the sorting behaves differently when fed a list using SQL Statements and when using Linq
var lstBoxes = new List<Record>();
var con = new SqlConnection(cs);
con.Open();
var command = new SqlCommand("SELECT ID,Type,Subject,CreatedBy,CreatedOn FROM Box", con);
SqlDataReader reader = command.ExecuteReader();
while (reader.Read())
{
lstBoxes.Add(new Record { Type = Convert.ToString(reader["Type"]), Id = Convert.ToString(reader["ID"]), Subject = Convert.ToString(reader["Subject"]), CreatedBy = Convert.ToString(reader["CreatedBy"]), CreatedOn = Convert.ToString(reader["CreatedOn"]) });
}
con.Close();
return lstBoxes;
Using Linq:
var lstBoxes = db.Boxs.Select(s => new Record
{ Type = s.Type, Id = s.ID.ToString(), Subject = s.Subject, CreatedBy = s.CreatedBy, CreatedOn = s.CreatedOn.ToString() }).ToList();
return lstEvents;
Even though both tables return same data, the sorting on the Created on works perfectly with SQL Server but not with LINQ. Is this a known issue?
EDIT : Removed the descending by in LINQ to make both code consistent.
EDIT 2 : I checked the results of both lists. There is a difference in the way the date is being retrieved.
For example : In SQL, the field Convert.ToString(reader["CreatedOn"]) is being retrieved as 11/7/2017 9:51:26 AM where as in LINQ CreatedOn = s.CreatedOn.ToString() gives Nov 7 2017 9:51 AM. This might be the cause of the issue. Is there a way the LINQ string be formatted similar to SQL result string?

Change TextBox Value and Update On Ajax Call

I am working on an ecommerce site where I am stuck on the cart management. Basically before login, products are kept in a session and I am trying to update the product quantity stored in the session using Ajax. I mean whenever I write in the 'Quantity To Change', the changed value should be reflected in the 'Quantity' column.
Note: I've shortened the post and figured out why it wasn't firing while debugging. Actually I was unable to get the id of the associated product. Now it passes the id. That's it. Now I've another issue - The TextBox are being created dynamically with a for loop. I used developer tools to figure out how the TextBoxes are generated dynamically and it is something like this:
For Product 1: cartDetails_0__Quantity
For Product 2: cartDetails_1__Quantity
I am wondering how to grab the quantity or values from the dynamically generated TextBoxes. If I put the generated id from HTML directly to Ajax, then it updates the quantity. Otherwise it doesn't. I've tried to use a loop in Ajax but I think, I am getting it wrong. Please see the View.
The view:
<table border="1" width="100%" cellpadding="4">
<thead>
<tr>
<th style="text-align:center;">Name</th>
<th style="text-align:center;">Price</th>
<th style="text-align:center;">Quantity</th>
<th style="text-align:center;">Quantity To Change</th>
</tr>
</thead>
<tbody>
#if (ViewBag.CartDetails != null)
{
for (int i = 0; i < cartDetails.Count(); i++)
{
<tr>
<td style="text-align: center; display:none;">#Html.DisplayFor(model => cartDetails[i].ProductId)</td>
<td id="ID" style="text-align: center;">#Html.DisplayFor(model => cartDetails[i].ProductName)</td>
<td style="text-align: center;">#Html.DisplayFor(model => cartDetails[i].Price)</td>
<td style="text-align: center;">#Html.DisplayFor(model => cartDetails[i].Quantity, new { #class = "quantityUpdate" })</td>
<td style="text-align: center;">#Html.TextBoxFor(model => cartDetails[i].Quantity, new { #class = "quantity", data_id = cartDetails[i].ProductId } )</td>
</tr>
}
}
</tbody>
</table>
<script src="~/Scripts/jquery-1.10.2.min.js"></script>
<script type="text/javascript">
var url = '#Url.Action("UpdateCart")';
$(".quantityUpdate").change(function () {
var id = $(this).data('id');
var i = 0;
$('.quantityUpdate').each(function (i, item) {
$.post(url, { id: id, Quantity: $("#cartDetails_"+i+"__Quantity").val() }, function (response) {
if (response) {
$("#TotalPrice").load(window.location + " #TotalPrice");
}
});
})
alert(id);
alert($("#cartDetails_"+i+"__Quantity").val());
});
Here is an image sample that I am trying:
$('.quantity').change(function(){
$('.quantityUpdate').val($('.quantity').val());
// put code here
});
Instant Change
$('.quantity').keyup(function(){
$('.quantityUpdate').val($('.quantity').val());
// put code here
});
If the idea is to call ajax when you change the value in .quality textbox then this is how you should do:
$('.quantity').change(function(){
//your ajax call
});

Categories