using DataContractJsonSerializer when Json object propety is named with "#" symbol - asp.net

When using DataContractJsonSerializer to parse a json response, I've come across a json object with a property name of #id and I can't seem to populate this field. All of the other fields are populated without a problem. I can even get this field populated using Fiddler, but not using DataContractJsonSerializer. My code is as follows...
public IEnumerable<Vehicle> vehicles { get; set; }
public async Task GetVehicleList(string access_token)
{
vehicles = await GetVehicleListInfo(access_token);
}
private async Task<IEnumerable<Vehicle>> GetVehicleListInfo(string access_token)
{
using (var client = new HttpClient())
{
client.BaseAddress = new Uri("https://www.example.com/");
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/vnd.example.api-v1+json"));
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer" + access_token);
HttpResponseMessage response = await client.GetAsync("vehicles");
//IEnumerable<Vehicle> vehicles = new IEnumerable<Vehicle>();
Vehicle vehicle = new Vehicle();
PagedVehicleResult pvr = new PagedVehicleResult();
Stream dataStream = null;
if (response.IsSuccessStatusCode)
{
dataStream = await response.Content.ReadAsStreamAsync();
DataContractJsonSerializer serializer = new DataContractJsonSerializer(pvr.GetType());
pvr = (PagedVehicleResult)serializer.ReadObject(dataStream);
}
vehicles = pvr.vehicle;
return vehicles;
}
}
}
/// <summary>
/// parent object returned by json. contains list of vehicle objects
/// </summary>
public class PagedVehicleResult
{
public int count { get; set; }
public int index { get; set; }
public int limit { get; set; }
public int total { get; set; }
public string type { get; set; }
public IEnumerable<Vehicle> vehicle { get; set; }
}
public class Vehicle
{
public int id { get; set; } //This is the property in question.
//When it comes back in fiddler it looks like "#id", and it does get populated.
//when it comes back in my console application it is 0 if int and null if string.
public string vin { get; set; }
public string label { get; set; }
public string color { get; set; }
public string make { get; set; }
public string model { get; set; }
public string deviceSerialNumber { get; set; }
public int year { get; set; } //consider making date? unknown repercussions
public CreateTimestamp createdTimestamp { get; set; }
public ModifiedTimestamp modifiedTimestamp { get; set; }
}
public class CreateTimestamp
{
public string readOnly { get; set; }
public string value { get; set; } //had to cast as string.. can convert to datetime before database insert
}
public class ModifiedTimestamp
{
public string readOnly { get; set; }
public string value { get; set; }
}
How can I map that json #id field to my Vehicle class id property?

Okay, I figured this out on my own from reading various different post on the subject.
All I had to do was parse it into a json string first, then call a .replace() on the string to change the id. Then I used the JavaScriptSerializer on that and it worked.
if (response.IsSuccessStatusCode)
{
dataStream = await response.Content.ReadAsStreamAsync();
string content;
using (StreamReader reader = new StreamReader(dataStream, true))
{
content = reader.ReadToEnd();
content = content.Replace("#id", "id");
JavaScriptSerializer js = new JavaScriptSerializer();
pvr = js.Deserialize<PagedVehicleResult>(content);
}
}
vehicles = pvr.vehicle;
return vehicles;
Now, when i try, my object id is correctly inserted.

Related

Adding a list of objects to SQL Server - ASP.NET Web API

I'm trying to add a list of objects to a SQL Server database via Entity Framework but I get an error with Add
[HttpPost]
public void Post(List<Row> rows)
{
try
{
using (DbModel dbModel = new DbModel())
{
foreach (var el in rows)
{
dbModel.Provider_Status.Add(el);
}
dbModel.SaveChanges();
}
}
catch { }
}
Row class:
public class Row
{
public string FileName { get; set; }
public string FileTitle { get; set; }
public string ProviderID { get; set; }
public string ServiceID { get; set; }
public string PublishDate { get; set; }
public string ExpiryDate { get; set; }
}
Database Model DbModel:
public partial class Provider_Status
{
public int Id { get; set; }
public string FileName { get; set; }
public string FileTitle { get; set; }
public string ProviderID { get; set; }
public string ServiceID { get; set; }
public string PublishDate { get; set; }
public string ExpiryDate { get; set; }
}
Error Message:
CS1503 Argument 1: cannot convert from 'File_Upload.Models.Row' to 'File_Upload.Models.Provider_Status
Your DbModel defines a data set of type Provider_Status - so if you want to add data to this data set, you need to provide Provider_Status objects - not Row objects (as you do now).
You need to convert those Row object to Provider_Status - try something like this:
[HttpPost]
public void Post(List<Row> rows)
{
try
{
using (DbModel dbModel = new DbModel())
{
foreach (var el in rows)
{
// create a new "Provider_Status" object, based on the
// "Row" values being passed in
Provider_Status status = new Provider_Status
{
FileName = el.FileName
FileTitle = el.FileTitle
ProviderID = el.ProviderID
ServiceID = el.ServiceID
PublishDate = el.PublishDate
ExpiryDate = el.ExpiryDate
};
// add that new Provider_Status object to your dbModel
dbModel.Provider_Status.Add(status);
}
dbModel.SaveChanges();
}
}
catch { }
}

Passing lists to the view .Net Core

Im looping through all the results from the SQL query in a .Net Core project. here is Model
public class Mymessagesinfo
{
public int MyMessagesCount { get; set; }
public List<int> MessagesIDs { get; set; }
public List<int> MessagesSendersid { get; set; }
public List<string> MessagesSenders { get; set; }
public List<string> MessagesTitles { get; set; }
public List<string> MessagesInformation { get; set; }
public List<string> MessagesStatus { get; set; }
}
I loop through the users messages in my controller then i pass that model to the view
sqlcon.Open();
int? userid = HttpContext.Session.GetInt32("UserID");
SqlCommand sqlcom = new SqlCommand("select * from messages where Messagereceiver=" +userid , sqlcon);
SqlDataReader reader = sqlcom.ExecuteReader();
if(reader.HasRows)
{
int index = 0;
while(reader.Read())
{
string s;
s = reader[0].ToString();
Mymessages.MessagesIDs.Add(int.Parse(s));
Mymessages.MessagesSendersid.Add(int.Parse(reader[1].ToString()));
Mymessages.MessagesTitles.Add(reader[3].ToString());
Mymessages.MessagesInformation.Add(reader[4].ToString());
Mymessages.MessagesStatus.Add(reader[5].ToString());
index++;
}
Mymessages.MyMessagesCount = index;
}
the very first line Mymessages.MessagesIDs.Add(int.Parse(s)); it throws an exception saying System.NullReferenceException: 'Object reference not set to an instance of an object
i wanted to make sure that reader was holding the results so i added int s and checked on it and it was holding the value it was supposed to.
whats going wrong here? is this how we are supposed to pass list-like data to the view?
You need to initlize MessagesIDs in entity Mymessages, like this:
var Mymessages = new Mymessagesinfo()
{
MessagesIDs = new List<int>()
};
Mymessages.MessagesIDs.Add(id);
Or just define the class like this,
public class Mymessagesinfo
{
public int MyMessagesCount { get; set; }
public List<int> MessagesIDs { get; set; } = new List<int>();
public List<int> MessagesSendersid { get; set; } = new List<int>();
public List<string> MessagesSenders { get; set; } = new List<string>();
public List<string> MessagesTitles { get; set; } = new List<string>();
public List<string> MessagesInformation { get; set; } = new List<string>();
public List<string> MessagesStatus { get; set; } = new List<string>();
}
Here is how I would restructure what you have to make it work.
First, your model class:
public class Mymessagesinfo
{
public List<MessageInfo> Messages { get; set; } = new List<MessageInfo>();
}
public class MessageInfo
{
public int ID { get; set; }
public int Senderid { get; set; }
public string Sender { get; set; }
public string Title { get; set; }
public string Information { get; set; }
public string Status { get; set; }
}
With this approach you have a list of message objects, instead of a bunch of lists containing property data.
Here is how I would suggest you load it from SQL Server:
var data = new Mymessagesinfo();
int? userid = HttpContext.Session.GetInt32("UserID");
var messagesTable = new System.Data.DataTable("messages");
using (var sqlcom = sqlcon.CreateCommand())
{
sqlcom.CommandText = $"select * from messages where Messagereceiver='{userid}'";
using (var adapter = new SqlDataAdapter(sqcom))
{
adapter.Fill(messagesTable);
}
}
// we are now done with SQL and have the data in memory...
foreach(DataRow row in messagesTable.Rows)
{
data.Messages.Add( new MessageInfo {
ID = row.Field<int>(0),
Senderid = row.Field<int>(1),
Sender = row.Field<string>(2),
Title = row.Field<string>(3),
Information = row.Field<string>(4),
Status = row.Field<string>(5),
});
}
return View(data);
This is a lot cleaner and by using a DataAdapter and DataTable you minimize the amount of time that the connection to the database is connected.
Here is how you would use this model in an MVC View:
#Model Mymessagesinfo
<div>
<!-- This is where you can display the properties of the message. //-->
<ul>
#foreach(var message in Model.Messages)
{
<li> #message.Title - #message.Id </li>
}
<ul>
<div>

asp.net web api list of list pass into json ajax

I have web api controller where I try to do something like this:
public IHttpActionResult Get()
{
var Rooms = db.Rooms.Select(r => new {
Id = r.Id,
Name = r.Name,
ChairNum = r.СhairNum,
Requests = r.Requests.ToList()
}).ToList();
return Ok(new { results = Rooms });
}
In Model I have this:
public partial class Room
{
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
public Room()
{
this.Requests = new HashSet<Request>();
}
public int Id { get; set; }
public string Name { get; set; }
public int СhairNum { get; set; }
public bool IsProjector { get; set; }
public bool IsBoard { get; set; }
public string Description { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<Request> Requests { get; set; }
}
I tried to pass this data in service. But I have serialization error, when I call http://localhost:99999/api/Rest.
<ExceptionMessage>
The "ObjectContent`1" type could not serialize the response text for the content type "application / json; charset = utf-8".
</ ExceptionMessage>
What is the best way to pass the data like in model into json?
It helped to put in WebApiConfig:
var json = config.Formatters.JsonFormatter;
json.SerializerSettings.PreserveReferencesHandling = Newtonsoft.Json.PreserveReferencesHandling.Objects;
config.Formatters.Remove(config.Formatters.XmlFormatter);

Post JSON Array in Asp.Net Web API

Hi every one I am new to ASP.Net Web API and I want to Post JSON array data any get there response.
My JSON POST Array format is
{
"User_Id":"admi12n#1234","Key_Code":"3F-47-AB-84-9F-EB-D6-6B-9C-62-CC-85-98-4D-28-6B",
"ProductDetails": [
{"Product_Id":"ELT-7035","Price":"999","Quantity":"5"},
{"Product_Id":"ELT-1254","Price":"1024","Quantity":"3"}
]
}
And I want response as follows
{
"User_Id":"admi12n#1234","Key_Code":"3F-47-AB-84-9F-EB-D6-6B-9C-62-CC-85-98-4D-28-6B",
"OrderID":"Ord-021","Name":"Sabyasachi"
"ProductDetails": [
{"Product_Id":"ELT-7035","Price":"999","Quantity":"5"},
{"Product_Id":"ELT-1254","Price":"1024","Quantity":"3"}
]
}
I generate OrderID as Random and Name from posted User_Id. Here I want to post multiple product in one order.
My Order class is as follows
public class Order
{
[Key]
public long ID { get; set; }
public string Order_Id { get; set; }
public string Product_Id { get; set; }
public long Quantity { get; set; }
public long Amount { get; set; }
public string User_Id { get; set; }
public string Key_Code { get; set; }
public DateTime Order_Date { get; set; }
public DateTime Modified_Date { get; set; }
}
And my Product class as follows
public class Product
{
[Key]
public int Id { get; set; }
public string Product_Code { get; set; }
public string Product_Name { get; set; }
public string Product_Category { get; set; }
public string Product_Description { get; set; }
public string Quantity { get; set; }
public string Price { get; set; }
public string Image { get; set; }
public DateTime Created_Date { get; set; }
public DateTime Modified_Date { get; set; }
}
I am not able to ind the best way to post the order
public Order Add(Order odrerDetails) //This will not give array of data for products
{
using (var context = new EcommerceDBContext())
{
odrerDetails.Order_Id = Helper.Random(7); //Generate random orderID from my class
odrerDetails.Created_Date = DateTime.Now;
odrerDetails.Modified_Date = DateTime.Now;
//How to Save other details
context.objOrderListing.Add(odrerDetails);
context.SaveChanges();
return odrerDetails;
}
}
In API controllers my code is as follows
public HttpResponseMessage PostOrder([FromBody] Order_Listing orderData)
{
orderData = repository.Add(orderData);
var response = Request.CreateResponse<Order_Listing>(HttpStatusCode.Created, orderData);
string uri = Url.Link("DefaultApi", new { customerID = orderData.ID });
response.Headers.Location = new Uri(uri);
return response;
}
Please help me how to achieve this.
There are several issues with your code:
Your Order and Product classes do not reflect the structure of
your JSON.
The Order class contains product details in a 1:1
relationship. Based on the JSON I assume you want a 1:n relationship.
Properties in your JSON need to have the same name as
in your classes or they won't be mapped.
Change your classes to the following and it should work.
Of course you could also change the property names in your JSON.
If you can't or don't want to change your property names, consider using DTOs
public class Order
{
public string User_Id { get; set; }
public string Key_Code { get; set; }
public string OrderID { get; set; }
public string Name { get; set; }
public List<Product> ProductDetails { get; set; }
// add the rest of your properties
}
public class Product
{
public string Product_Id { get; set; }
public string Price { get; set; }
public string Prd_Qty { get; set; }
// add the rest of your properties
}
Update: added code for Add method and Api method
Your Add method would look like this:
public Order Add(Order orderWithDetails)
{
using (var context = new EcommerceDBContext())
{
orderWithDetails.Order_Id = Helper.Random(7); //Generate random orderID from my class
orderWithDetails.Created_Date = DateTime.Now;
orderWithDetails.Modified_Date = DateTime.Now;
context.objOrderListing.Add(orderWithDetails);
// Save each Product
foreach (var detail in orderWithDetails.ProductDetails)
{
//whatever you need to do in your db-context
context.objOrderDetails.Add(detail); // just an example
}
context.SaveChanges();
return orderWithDetails;
}
}
The signature of your Api method looks wrong. What is Order_Listing? This should be Order, unless it's a DTO, in wich case you need a method to get an Order from Order_Listing.
public HttpResponseMessage PostOrder([FromBody] Order orderData)
{
orderData = repository.Add(orderData);
var response = Request.CreateResponse<Order_Listing>(HttpStatusCode.Created, orderData);
string uri = Url.Link("DefaultApi", new { customerID = orderData.ID });
response.Headers.Location = new Uri(uri);
return response;
}
A few more remarks:
If it is indeed a 1:n relationship, you probably need a property Product.OrderId.
The Order class should not have any reference to Product except for the list.
Quantity and Price should most likely not be String but numerical values, e.g. decimal.
If Order.ID is your primary key, then having Order.Order_ID is really confusing. Consider renaming it to Order.Order_Number.
public class Order
{
public string User_Id { get; set; }
public string Key_Code { get; set; }
public string OrderID { get; set; }
public string Name { get; set; }
public Product[] ProductDetails { get; set; }
}

ASP.NET Cannot get FULL list of ALL countries in the world

There are 196 countries in the world.
I'm trying to show a dropdown list that show all of them.
I see many developer suggest using CultureInfo of ASP.NET but it's missing some countries because Culture & Country are different things.
So how can I get a list of all countries for my purpose please ?. I really appreciate your help.
In ASP.NET a DropDown
<asp:DropDownList ID="selCountries" runat="server"></asp:DropDownList>
is equivalent to
<select id="selCountries"></select>
Alternatively, you could use a Web service to fill a select tag with countries through JavaScript XMLHttpRequest object.
Example: https://restcountries.eu/
Something like this:
(function() {
var newXHR;
function sendXHR(options) { // Helper function.
newXHR = new XMLHttpRequest() || new ActiveXObject("Microsoft.XMLHTTP");
if (options.sendJSON === true) {
options.contentType = "application/json; charset=utf-8";
options.data = JSON.stringify(options.data);
} else {
options.contentType = "application/x-www-form-urlencoded";
}
newXHR.open(options.type, options.url, options.async || true);
newXHR.setRequestHeader("Content-Type", options.contentType);
newXHR.send((options.type == "POST") ? options.data : null);
newXHR.onreadystatechange = options.callback;
return newXHR;
}
sendXHR({
type: "GET",
url: "https://restcountries.eu/rest/v1/all",
callback: function() {
if (newXHR.readyState === 4 && newXHR.status === 200) {
var data = JSON.parse(newXHR.response);
var selCountries = document.getElementById("selCountries"); // Get the select tag.
// You can get the selected country.
selCountries.onchange = function() {
alert(this.value);
};
var option;
for (var i = 0; i < data.length; i++) { // For every country make an option tag.
option = document.createElement("option");
selCountries.options.add(option, 0);
selCountries.options[0].value = data[i].name; // Country name from the index «i» of the data array.
selCountries.options[0].innerText = data[i].name;
selCountries.appendChild(option); // Append the option tag to the select tag.
}
}
}
});
})();
<select id="selCountries"></select>
In ASP.NET MVC5 NET 4.5, you can bind an object to #Html.DropDownList by using ViewBag.
You need to create a model according to https://restcountries.eu/rest/v1/all json response.
Model: CountryModel.cs
using System.Collections.Generic;
namespace RestCountries.Models
{
public class Translations
{
public string de { get; set; }
public string es { get; set; }
public string fr { get; set; }
public string ja { get; set; }
public string it { get; set; }
}
public class CountryModel
{
public string name { get; set; }
public string capital { get; set; }
public List<string> altSpellings { get; set; }
public string relevance { get; set; }
public string region { get; set; }
public string subregion { get; set; }
public Translations translations { get; set; }
public int population { get; set; }
public List<object> latlng { get; set; }
public string demonym { get; set; }
public double? area { get; set; }
public double? gini { get; set; }
public List<string> timezones { get; set; }
public List<object> borders { get; set; }
public string nativeName { get; set; }
public List<string> callingCodes { get; set; }
public List<string> topLevelDomain { get; set; }
public string alpha2Code { get; set; }
public string alpha3Code { get; set; }
public List<string> currencies { get; set; }
public List<object> languages { get; set; }
}
}
Controller: DefaultController.cs
using RestCountries.Models;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Web.Mvc;
namespace RestCountries.Controllers
{
public class DefaultController : Controller
{
// GET: Default
public ActionResult Index()
{
string url = "https://restcountries.eu/rest/v1/all";
// Web Request with the given url.
WebRequest request = WebRequest.Create(url);
request.Credentials = CredentialCache.DefaultCredentials;
WebResponse response = request.GetResponse();
Stream dataStream = response.GetResponseStream();
StreamReader reader = new StreamReader(dataStream);
string jsonResponse = null;
// Store the json response into jsonResponse variable.
jsonResponse = reader.ReadLine();
if (jsonResponse != null)
{
// Deserialize the jsonRespose object to the CountryModel. You're getting a JSON array [].
List<CountryModel> countryModel = Newtonsoft.Json.JsonConvert.DeserializeObject<List<CountryModel>>(jsonResponse);
// Set the List Item with the countries.
IEnumerable<SelectListItem> countries = countryModel.Select(x => new SelectListItem() { Value = x.name, Text = x.name });
// Create a ViewBag property with the final content.
ViewBag.Countries = countries;
}
return View();
}
}
}
View: Index.cshtml
#{
ViewBag.Title = "Index";
}
<h2>Index</h2>
#Html.DropDownList("Countries")
Result:

Resources