I have the following classes:
[DataContract]
public class MapServiceInfo
{
private EventHandler _infoRetrievalFinished;
public event EventHandler InfoRetrievalFinished
{
add
{
if (this._infoRetrievalFinished == null ||
!this._infoRetrievalFinished.GetInvocationList().Contains(value))
{
this._infoRetrievalFinished += value;
}
}
remove { this._infoRetrievalFinished -= value; }
}
[DataMember] public string currentVersion { get; set; }
[DataMember] public string serviceDescription { get; set; }
[DataMember] public string mapName { get; set; }
[DataMember] public string description { get; set; }
[DataMember] public string copyrightText { get; set; }
[DataMember] public bool supportsDynamicLayers { get; set; }
[DataMember] public List<LayerInfo> layers { get; set; }
public MapServiceInfo() { }
public void RetrieveServiceInfo(string mapServiceUrl)
{
string url = mapServiceUrl.TrimEnd("/".ToCharArray()) + "?f=json";
WebClient webClient = new WebClient();
webClient.OpenReadCompleted += new OpenReadCompletedEventHandler(webClient_OpenReadCompleted);
webClient.OpenReadAsync(new Uri(url));
}
private void webClient_OpenReadCompleted(object sender, OpenReadCompletedEventArgs e)
{
if (e.Error == null)
{
MapServiceInfo info = null;
try
{
Stream responseStream = e.Result;
StreamReader reader = new StreamReader(responseStream);
DataContractJsonSerializer serializer =
new DataContractJsonSerializer(typeof(MapServiceInfo));
info = (MapServiceInfo)serializer.ReadObject(responseStream);
}
catch (Exception ex) { string message = ex.Message; }
finally { this.SetInfo(info); }
}
else { /**/ }
}
public string GetLayerId(string layerName)
{
Debug.Assert(!(string.IsNullOrEmpty(layerName)));
Debug.Assert(!(string.IsNullOrWhiteSpace(layerName)));
if (layerName == null) { throw new ArgumentNullException("layerName"); }
else if (string.IsNullOrEmpty(layerName)) { return ""; }
else if (string.IsNullOrWhiteSpace(layerName)) { return ""; }
string id = string.Empty;
if (layers != null)
{
foreach (LayerInfo i in layers)
{
if (i.name == layerName)
{
id = i.id.ToString();
break;
}
else { continue; }
}
}
else { /**/ }
return id;
}
private void SetInfo(MapServiceInfo info)
{
Debug.Assert(!(info == null));
if (info != null)
{
this.currentVersion = info.currentVersion;
this.serviceDescription = info.serviceDescription;
this.mapName = info.mapName;
this.description = info.description;
this.copyrightText = info.copyrightText;
this.supportsDynamicLayers = info.supportsDynamicLayers;
this.layers = info.layers;
this.TriggerInfoRetrievalFinished();
}
else { /* Do nothing. */ }
}
private void TriggerInfoRetrievalFinished()
{
if (this._infoRetrievalFinished != null) { this._infoRetrievalFinished(this, null); }
}
}
[DataContract]
public class LayerInfo
{
[DataMember] public int id { get; set; }
[DataMember] public string name { get; set; }
[DataMember] public int parentLayerId { get; set; }
[DataMember] public bool defaultVisibility { get; set; }
[DataMember] public List<int> subLayerIDs { get; set; }
[DataMember] public int minScale { get; set; }
[DataMember] public int maxScale { get; set; }
}
The very first time I run my Silverlight app I get the Visual Studio Just-In-Time Debugger popping up saying, "An unhandled exception ('Unhandled Error in Silverlight Application Code: 4004 Category: ManagedRuntimeError Message: System.Runtime.Serialization.SerializationException: 'html>".
If I say "No" to "Do you want to debug using the selected debugger?" and refresh the web page, the error does not return and my app runs as expected. It only happens the very first time I go into debug.
I have determined that the exception is thrown right after the curly brace that comes after my finally block under webClient_OpenReadCompleted(), just before the else statement. Nothing is caught in my catch statement.
I have never seen this before. Does anyone know what might be going on?
The problem is the data read is not valid serialized JSON.
The indicator in the error message - SerializationException: 'html><head> - is a give-away that the data is an [X]HTML document, not the JSON expected.
Then it's just a matter of finding out (and fixing) why such occurs - perhaps the server responded with a custom 403 or 404 response at such a time?
This issue, however, is separate from serialization - invalid data cannot be reliably deserialized.
Related
I am stumped on this for a couple of hours.
I am using WebApi 2 and Entity Framework 6.1.3. I am following this tutorial:
https://learn.microsoft.com/en-us/aspnet/web-api/overview/data/using-web-api-with-entity-framework/
I would like to return only json. When I hit url http://localhost:11440/Api/Contacts. I am getting following error:
The 'ObjectContent`1' type failed to serialize the response body for content type 'application/xml; charset=utf-8'.
I have the following models and controller defined:
Address.cs
namespace Blah_Application.Models
{
public class Address
{
public int AddressID { get; set; }
public int ContactID { get; set; }
public string Street { get; set; }
public string City { get; set; }
public string State { get; set; }
public string Country { get; set; }
public string ZipCode { get; set; }
public double Latitude { get; set; }
public double Longitude { get; set; }
public virtual Contact Contact { get; set; }
}
}
Contact.cs
using System.Collections.Generic;
namespace Blah_Application.Models
{
public class Contact
{
public Contact()
{
Phones = new HashSet<Phone>();
Addresses = new HashSet<Address>();
}
public int ContactID { get; set; }
public string Name { get; set; }
public string Company { get; set; }
public bool Favorite { get; set; }
public string SmallImageUrl { get; set; }
public string LargeImageUrl { get; set; }
public string Email { get; set; }
public string Website { get; set; }
public string BirthDate { get; set; }
public virtual ICollection<Phone> Phones { get; set; }
public virtual ICollection<Address> Addresses { get; set; }
}
}
Phone.cs
namespace Ecitslos_Application.Models
{
public enum PhoneType { Home, Work, Mobile}
public class Phone
{
public int PhoneID {get; set;}
public int ContactID { get; set; }
public PhoneType PhoneType { get; set; }
public string Number { get; set; }
public virtual Contact Contact { get; set; }
}
}
ContactsController.cs
using System.Data.Entity;
using System.Data.Entity.Infrastructure;
using System.Linq;
using System.Net;
using System.Web.Http;
using System.Web.Http.Description;
using Blah_Application.Models;
namespace Ecitslos_Application.Controllers
{
public class ContactsController : ApiController
{
private Ecitslos_ApplicationContext db = new
Ecitslos_ApplicationContext();
// GET: api/Contacts
public IQueryable<Contact> GetContacts()
{
return db.Contacts;
}
// GET: api/Contacts/5
[ResponseType(typeof(Contact))]
public IHttpActionResult GetContact(int id)
{
Contact contact = db.Contacts.Find(id);
if (contact == null)
{
return NotFound();
}
return Ok(contact);
}
// PUT: api/Contacts/5
[ResponseType(typeof(void))]
public IHttpActionResult PutContact(int id, Contact contact)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
if (id != contact.ContactID)
{
return BadRequest();
}
db.Entry(contact).State = EntityState.Modified;
try
{
db.SaveChanges();
}
catch (DbUpdateConcurrencyException)
{
if (!ContactExists(id))
{
return NotFound();
}
else
{
throw;
}
}
return StatusCode(HttpStatusCode.NoContent);
}
// POST: api/Contacts
[ResponseType(typeof(Contact))]
public IHttpActionResult PostContact(Contact contact)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
db.Contacts.Add(contact);
db.SaveChanges();
return CreatedAtRoute("DefaultApi", new { id = contact.ContactID }, contact);
}
// DELETE: api/Contacts/5
[ResponseType(typeof(Contact))]
public IHttpActionResult DeleteContact(int id)
{
Contact contact = db.Contacts.Find(id);
if (contact == null)
{
return NotFound();
}
db.Contacts.Remove(contact);
db.SaveChanges();
return Ok(contact);
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
db.Dispose();
}
base.Dispose(disposing);
}
private bool ContactExists(int id)
{
return db.Contacts.Count(e => e.ContactID == id) > 0;
}
}
}
You need to disable the XML formatter that is configured by default. Add the following line to the WebApiConfig class:
public static class WebApiConfig {
public static void Register(HttpConfiguration config) {
//route config etc. goes here
//disable xml serialization
config.Formatters.Remove(config.Formatters.XmlFormatter);
//prevent infinite recusion
config.Formatters.JsonFormatter.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
}
}
Way I am doing this in my project is the following. Hope you can get a pointer in the right direction.
// GET: api/Contacts/5
<Route("~/api/Contacts/{id}")>
<HttpGet>
public HttpResponseMessage GetContact(int id)
{
Contact contact = db.Contacts.Find(id);
if (contact == null)
{
Return Request.CreateResponse(HttpStatusCode.NotFound, "Contact Id not found", Configuration.Formatters.JsonFormatter);
}
Return Request.CreateResponse(HttpStatusCode.OK, contact, Configuration.Formatters.JsonFormatter);
}
Also, you have Contact in Phone and then you are instantiating Phone in Contact. This may create a cyclic dependency.
i am new to windows phone development and so by references implemented some code but i am not able to get the desired result.
i want to parse a JSON that is received as a response from the server.
Please find below my code.
class JSONParsing
{
public Status response { get; set; }
public static void webClient1_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
{
if (!String.IsNullOrEmpty(e.Result))
{
try
{
JSONParsing root = JsonConvert.DeserializeObject<JSONParsing>(e.Result);
// root is null here
JObject obj = root.response.statusDetail;
// from here it goes to Catch block
foreach (KeyValuePair<string, JToken> pair in obj)
{
string key = pair.Key;
foreach (JObject detail in pair.Value as JArray)
{
string Code = detail["Code"].ToString();
string Msg = detail["Msg"].ToString();
string RegistrationID = detail["RegistrationID"].ToString();
string Name = detail["Name"].ToString();
string Phone = detail["Phone"].ToString();
string email = detail["email"].ToString();
string password = detail["password"].ToString();
}
}
}
catch (Exception ex)
{
Console.WriteLine("Cause of Exception is " + ex.Message);
// exception is-- "Object reference not set to an instance of an object."
}
} // if for empty
}
}
public class Status
{
public string Code { get; set; }
public string Msg { get; set; }
public object RegistrationID { get; set; }
public string Name { get; set; }
public string Phone { get; set; }
public string email { get; set; }
public string password { get; set; }
[JsonProperty("")]
public JObject statusDetail { get; set; }
}
public class RootObject
{
public List<Status> Status { get; set; }
public int success { get; set; }
}
}
Please Help.
If root is null the class 'JSONParsing' is not having same class structure as the json
and since root is null, accessing property inside a null('root.response.statusDetail') will throw an exception
you can use http://json2csharp.com/ to get the class structure of the json
I'm trying to parse a JSON file when someone clicks on a button, which replaces the button's Content with data from the JSON.
Currently I'm facing an issue where the data remains null. The code is as follows:
private void Button1_Tap(object sender, System.Windows.Input.GestureEventArgs e)
{
Button1.FontSize = 15;
Button1.Content = "Fetching...";
var client = new WebClient();
client.OpenReadCompleted +=
(s, eargs) =>
{
var serializer = new DataContractJsonSerializer(typeof(RadioRootObject));
if (eargs.Error != null)
{
if (eargs.Error.Message.Contains("NotFound"))
{
MessageBox.Show("Could not retrieve playlist", "Error", MessageBoxButton.OK);
Button1.Content = "Could not retrieve playlist";
}
else
{
MessageBox.Show("Could not retrieve playlist", "Error", MessageBoxButton.OK);
Button1.Content = "Could not retrieve playlist";
}
}
else
{
var root = (RadioRootObject)serializer.ReadObject(eargs.Result);
var songHistory = root.station3;
Button1.Content = songHistory.text;
}
};
var uri = new Uri("http://www.reignofcomputer.com/tmpsend/nowplaying.json");
client.OpenReadAsync(uri);
}
public class station1
{
public string station { get; set; }
public string title { get; set; }
public string artist { get; set; }
public string text { get; set; }
}
public class station2
{
public string station { get; set; }
public int listeners { get; set; }
public string title { get; set; }
public string artist { get; set; }
public string text { get; set; }
}
public class station3
{
public string station { get; set; }
public int listeners { get; set; }
public string title { get; set; }
public string artist { get; set; }
public string text { get; set; }
}
public class RadioRootObject
{
public station1 station1 { get; set; }
public station2 station2 { get; set; }
public station3 station3 { get; set; }
}
root and songHistory remain null and thus throws a NullReferenceException.
station1 and station2 are used in Button2_Tap and Button3_Tap, not shown in the above code, which are similar to Button1_Tap above.
I'm told that the DataContractJsonSerializer cannot match property "1" from the json object to the property station1 on the RadioRootObject class, but I'm not sure how go about making it match.
I am unable to alter the data in the JSON itself. Any ideas?
Check this blog post for how to Parsing JSON in a Windows Phone Application
And accordingly, try this
private void Button_Click(object sender, RoutedEventArgs e)
{
Button1.FontSize = 15;
Button1.Content = "Fetching...";var client = new WebClient();
var uri = new Uri("http://www.reignofcomputer.com/tmpsend/nowplaying.json");
client.DownloadStringCompleted += new DownloadStringCompletedEventHandler(client_DownloadStringCompleted);
client.DownloadStringAsync(uri);
}
void client_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
{
var jobj = JObject.Parse(e.Result);
var station3 = jobj["3"];
Button1.Content = station3["text"];
}
Since the property in the JSON is "1" and the name of the member of RadioRootObject is "station1", these don't match. You can tell the serializer what the name in JSON is by using a DataMemberAttribute, something like
public class RadioRootObject
{
[DataMember(Name="1")]
public station1 station1 { get; set; }
[DataMember(Name="2")]
public station2 station2 { get; set; }
[DataMember(Name="3")]
public station3 station3 { get; set; }
}
Honestly, I thought you had to have [DataContract] and [DataMember] attributes on your class and members anyway (see the example for DataContractJsonSerializer), but I could be wrong :-)
I have been working on this for some time, i can read the last part, so everything from the square bracket to the end. But i can't read anything before that, when i put it in i Get a NullExceptionReference.
Here's the code I have got:
namespace WP7_ConsumeJSON
{
public partial class MainPage : PhoneApplicationPage
{
// Constructor
public MainPage()
{
InitializeComponent();
myButton.Click += new RoutedEventHandler(myButton_Click);
}
void myButton_Click(object sender, RoutedEventArgs e)
{
try
{
WebClient webClient = new WebClient();
Uri uri = new Uri("http://www.ournu.co.uk/list.txt");
webClient.OpenReadCompleted += new OpenReadCompletedEventHandler(webClient_OpenReadCompleted);
webClient.OpenReadAsync(uri);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
void webClient_OpenReadCompleted(object sender, OpenReadCompletedEventArgs e)
{
DataContractJsonSerializer ser = null;
try
{
ser = new DataContractJsonSerializer(typeof(ObservableCollection<Employee>));
ObservableCollection<Employee> employees = ser.ReadObject(e.Result) as ObservableCollection<Employee>;
foreach (Employee em in employees)
{
string id = em.ServiceName;
string dt = em.Destination;
string tm = em.DepartureTimeAsString;
listBoxService.Items.Add(id);
listBoxDestination.Items.Add(dt);
listBoxTime.Items.Add(tm);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
}
}
This is the feed result
{
"StopName":"Race Hill",
"stopId":7553,
"NaptanCode":"bridwja",
"LongName":"Race Hill",
"OperatorsCode1":"07645",
"OperatorsCode2":"7645",
"OperatorsCode3":"50701",
"OperatorsCode4":"bridwja",
"Departures":[
{
"ServiceName":"22",
"Destination":"Churchill Sq",
"DepartureTimeAsString":"1 min",
"DepartureTime":"01/01/0001 00:00:00",
"Notes":""
}
,
{
"ServiceName":"37",
"Destination":"Bristol Estate",
"DepartureTimeAsString":"1 min",
"DepartureTime":"01/01/0001 00:00:00",
"Notes":""
}
]}
So what do i need to do modify in the code in order for me to be able to read the first part of the code.
{
"StopName":"Race Hill",
"stopId":7553,
"NaptanCode":"bridwja",
"LongName":"Race Hill",
"OperatorsCode1":"07645",
"OperatorsCode2":"7645",
"OperatorsCode3":"50701",
"OperatorsCode4":"bridwja",
"Departures":[
Structure of the employee class:
namespace WP7_ConsumeJSON
{
public class Employee
{
public string StopName { get; set; }
public int stopId { get; set; }
public string NaptanCode { get; set; }
public string LongName { get; set; }
public string OperatorsCode1 { get; set; }
public string OperatorsCode2 { get; set; }
public string OperatorsCode3 { get; set; }
public string OperatorsCode4 { get; set; }
public string ServiceName { get; set; }
public string Destination { get; set; }
public string DepartureTimeAsString { get; set; }
public string DepartureTime { get; set; }
public string Notes { get; set; }
}
}
Download project - WP7_JSON.zip
You need to have a container class for the ObservableCollection<Employee> as to gather all that data!
public class RootContainer
{
[DataMember]
public string StopName { get; set; }
[DataMember]
public int stopId { get; set; }
[DataMember]
public string NaptanCode { get; set; }
//Other root properties go here
[DataMember]
public ObservableCollection<Employee> Employees { get; set; }
}
Then change the code like this:
void webClient_OpenReadCompleted(object sender, OpenReadCompletedEventArgs e)
{
DataContractJsonSerializer ser = null;
try
{
ser = new DataContractJsonSerializer(typeof(RootContainer));
RootContainer rootContainer = ser.ReadObject(e.Result) as RootContainer;
foreach (Employee em in rootContainer.Employees)
{
string id = em.ServiceName;
string dt = em.Destination;
string tm = em.DepartureTimeAsString;
listBoxService.Items.Add(id);
listBoxDestination.Items.Add(dt);
listBoxTime.Items.Add(tm);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
(I wrote the changes with Nodepad, hope I didn't make any error...)
I keep getting this error when i run my MVC application. The app builds fine but throws this error on the runtime.
Here is the scenario.
[DisplayColumn("Name", "Name", false)]
public partial class ApplicationAction
{
public Guid ApplicationActionId { get; set; }
[Required, StringLength(150), Column("ActionName")]
public string Action { get; set; }
[Required, StringLength(150)]
public string Controller { get; set; }
[StringLength(150)]
public string Area { get; set; }
[StringLength(250)]
public string Description { get; set; }
//Navigation Properties
public virtual ICollection<ApplicationActionGroup> ApplicationActionGroups { get; set; }
public ApplicationAction()
{
ApplicationActionId = Guid.NewGuid();
}
}
public DbSet<ApplicationAction> ApplicationActions { get; set; }
public static ApplicationAction GetAction(string actionName, string controller, string area, IEnumerable<ApplicationAction> actions)
{
foreach (ApplicationAction a in actions)
{
if (a.Action.Equals(actionName, StringComparison.InvariantCultureIgnoreCase)
&& a.Controller.Equals(controller, StringComparison.InvariantCultureIgnoreCase)
&& (
(string.IsNullOrEmpty(a.Area) && string.IsNullOrEmpty(area)) ||
(!string.IsNullOrEmpty(a.Area) && a.Area.Equals(area, StringComparison.InvariantCultureIgnoreCase))
)
)
{
return a;
}
}
return null;
}
I get an error on GetAction method. It comes up as Invalid object name 'dbo.ApplicationAction'. The sql database, there is a table called ApplicationActions. Not sure whats causing this error.
are you sure that [DisplayColumn("Name", "Name", false)]
is a valid attribute for a class?