Json deserialize into own class - asp.net-mvc-3

I'm using asp.net mvc4 and json.net
and i have a json structure like http://api.domaintools.com/v1/domaintools.com/whois/
How can i deserialize it into my own class ? This looks a bit complicated structure to me to realize how to build my class ?
Nam Vo

You can use the following class structure:
public class Response
{
public string Registrant {get;set;}
public Registration registration {get;set;}
public WhoIs whois {get;set;}
}
public class Registration
{
public DateTime created {get;set;}
public DateTime expires {get;set;}
public DateTime updated {get;set;}
public string registrar {get;set;}
public List<string> statuses {get;set;}
public List<string> name_servers {get;set;}
}
public class WhoIs
{
public DateTime date {get;set;}
public string record {get;set;}
}
You can then do like below:
Response response = JsonSerializer.DeserializeFromString<Response>(data);//data is your data from the link you have given in the problem description
Thus the data is now deserialized into your own class Response...hope this helps....

Related

WebApi action losing child collection from posted json

Suppose I post an object like this
{"Dto" : {
"DtoId" : 1,
"DtoThing" : "Some value",
"DtoChildStuff" : [{"CsId" : 1, "ChildProperty" : "SomeThing"}]
}}
to a WebApi action like this
[HttpPost]
public Response<MyDto> Post(DtoWrapper<MyDto> input)...
where the parameter is just some object with a property MyDto of type MyDto, and MyDto is like this
[DataContract]
public class MyDto
{
[DataMember]
public int DtoId {get;set;}
[DataMember]
public string DtoThing {get;set;}
[DataMember]
public List<ChildStuffDto> DtoChildStuff {get;set;}
}
[DataContract]
public class ChildStuffDto
{
[DataMember]
public int CsId {get;set;}
[DataMember]
public string ChildProperty {get;set;}
}
and (by the way) the DtoWrapper is just
public class DtoWrapper<T>
{
public T Dto {get;set;}
// So that I can add some other info that I need //
}
Why can't the action see any child objects. If I change the type on the parameter to object, I can see the child object being posted in, but it doesn't get deserialised. Any ideas?
Ok here's my answer, but I'd love to know if there's a way I can get it to happen without adding this line of code to my action.
public Response<MyDto> Post(object input)
{
dynamic myWrapperObj = JsonConvert.DeserializeObject<SomeWrapperForMyDto>
(input.ToString());
...
If that's how it has to be then fair play, but it seems a shame. Thanks for any posts :)

ASP.net Web Api layer between domain and what is serialized

In standard .NET MVC we have our Domain classes and we have ModelView classes. Now, with ASP.Net Web API I suppose there is no need for ModelView classes (since we are returning data) but should we return (serialized) Domain classes directly or there is a need for something in between?
// Domain class
public class User {
public int Id {get;set;}
public string FirstName {get;set;}
public string LastName {get;set;}
}
// inter class
public class ProductModel {
public int Id {get;set;}
public string FirstName {get;set;}
public string LastName {get;set;}
public string FullName {get {return String.Format("{0} {1}", FirstName, LastName);}}
}
// Controller V1 returns Product
public class UserController : ApiController
{
public Product GetProduct(int id) {...}
}
// Controller V2 returns ProductModel
public class UserController : ApiController
{
public ProductModel GetProduct(int id) {...}
}
Exposing your domain model in a API is rarely a good idea.
If you are the only one who will be consuming the API and you can be sure that you will deploy updates to the client and the server at exactly the same frequency, then you may be able to take this shortcut, however, I wouldn't recommend it.

asp.NET MVC 3 Composite pattern model binding

My application has products and vendors and both of them have similar items in a "has a" relationship...in particular they have a "favorite" so users can bookmark them.
so we have:
public class Product
{
public int ProductId {get;set;}
public int Name {get;set;}
public List<Favorite> Favorites {get;set;}
}
public class Vendor
{
public int VendorId {get;set;}
public int Name {get;set;}
public List<Favorite> Favorites {get;set;}
}
public class Favorite
{
public int FavoriteId {get;set;}
public string UserName {get;set;}
}
At first this didn't work, so I added:
public int? VendorId {get;set;}
public int? ProductId {get;set;}
Now the issue I'm having is that my Vendor.Favorites and Product.Favorites are always null.
How do I bind these so that I can work with the objects like that? Do I not make it a separate entity?
Thanks!
UPDATE: I should note that I'm using MVC 3 Code-first with POCO.
UPDATE: Solution:
I don't think this is ideal, still working out the kinks with how I want this to work because It will add redundant code for adding favorites and reviews.
public class Product
{
public int ProductId {get;set;}
public int Name {get;set;}
public virtual List<Favorite> Favorites {get;set;}
}
public class Vendor
{
public int VendorId {get;set;}
public int Name {get;set;}
public virtual List<Favorite> Favorites {get;set;}
}
Having the raw nullable int variable in the favorites class makes it work, but if I wanted to use the favorites class with other objects I'll have to modify the favorites properties with a new mapping to the key of the object. Out of curiosity, when dealing with these classes normally, how do you manage the data storage for these objects? I'm assuming you deal with it at a DAL?
You could use inheritance, make a base class containing only Favorite then derive classes based on that for the other info. This establishes an "is a" relationship
Ex.
public class baseClass
{
public list<Favorite> Favorites { get; set;}
}
public class Product : base
{
public int ProductID { get; set; }
public string Name { get; set; }
}
Then a Product Object would have all 3 properties.
Based on the assumption that you're using EF 4.1:
Your model looks pretty good except I'd change
public int? VendorId {get;set;}
public int? ProductId {get;set;}
to
public virtual Vendor VendorId {get;set;}
public virtual Product ProductId {get;set;}
Then your FK relationships should be all set. By my understanding of EF, List<Favorite> is meant to establish a relationship and is not actually populated. You have to populate it yourself, either by calling .Include() on the context or by referencing the actual FK that EF creates in the database, which in your case would be VendorId_FavoriteId or ProductId_FavoriteId
I would keep one Property to store the ID's (either VendorID or ProductId) and use another property to tell me what type it is (Vendor or Product)
public class Favorite
{
public int FavoriteId {get;set;}
public string UserName {get;set;}
public int ItemID { set;get;} //can use a better generic name
public FavoriteType Type { set;get;}
}
I have an Enum for the Types
public enum FavoriteType
{
Vendor,
Product
}
And make sure you are initializing your sub properties before accessing them / applying a method on those so that It won't throw the null reference exception!. You can do it constructor itself
public class Product
{
public int ProductId {get;set;}
public int Name {get;set;}
public List<Favorite> Favorites {get;set;}
public Product()
{
if(Favourites==null)
Favorites=new List<Favorite>();
}
}

How to separate large table into multiple discrete types using EF-Code-First

I am trying to separate a large table into multiple discrete types.
I'm following the example here: http://weblogs.asp.net/manavi/archive/2011/04/24/associations-in-ef-4-1-code-first-part-4-table-splitting.aspx?CommentPosted=true#commentmessage
It's working for a primary type and a sub-type, but does not work when I employ multiple types. I received an error
The Entity types 'CampaginFeedback' and 'CampaignSurvey' cannot share table 'Campaign' because they are not int he same type hierarchy
or do not have a valid one to one foreign key relationship with
matching primary keys between them.
Here are simplified versions of my classes:
public class Campaign {
[Key]
public int CampaignId {get;set;}
public string Name {get;set;}
public virtual CampaignSurvey Survey {get;set;}
public virtual CampaignFeedback Feedback {get;set;}
}
public class CampaignSurvey {
[Key]
public int CampaignId {get;set;}
public string Question {get;set;}
public string Answer {get;set;}
}
public class CampaignFeedback {
[Key]
public int CampaignId {get;set;}
public string Feedback {get;set;}
}
protected override void OnModelCreating(DbModelBuilder modelBuilder) {
modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
modelBuilder.Entity<Campaign>().HasRequired(c => c.Survey).WithRequiredPrincipal();
modelBuilder.Entity<Campaign>().HasRequired(c => c.Feedback).WithRequiredPrincipal();
modelBuilder.Entity<Campaign>().ToTable("Campaign");
modelBuilder.Entity<CampaignSurvey>().ToTable("Campaign");
modelBuilder.Entity<CampaignFeedback>().ToTable("Campaign");
}
Edit: Split table to more than two entities in code first is very problematic. It works without any problem when using EDMX.
To make it work you must ensure that each entity used to split table has valid one-to-one relation with all other entities used to split table. That also means spoiling your model with navigation properties and moreover ensuring that during save all navigation properties pointing to the same entity type reference the same instance (otherwise you will get exception during call to SaveChanges).
So the solution for your example should be something like:
public class Campaign {
[Key]
public int CampaignId {get;set;}
public string Name {get;set;}
public virtual CampaignSurvey Survey {get;set;}
public virtual CampaignFeedback Feedback {get;set;}
}
public class CampaignSurvey {
[Key]
public int CampaignId {get;set;}
public string Question {get;set;}
public string Answer {get;set;}
public virtual CampaignFeedback Feedback {get;set;}
}
public class CampaignFeedback {
[Key]
public int CampaignId {get;set;}
public string Feedback {get;set;}
}
protected override void OnModelCreating(DbModelBuilder modelBuilder) {
modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
modelBuilder.Entity<Campaign>().HasRequired(c => c.Survey).WithRequiredPrincipal();
modelBuilder.Entity<Campaign>().HasRequired(c => c.Feedback).WithRequiredPrincipal();
modelBuilder.Entity<CampaignSurvey>().HasRequired(c => c.Feedback).WithRequiredPrincipal();
modelBuilder.Entity<Campaign>().ToTable("Campaign");
modelBuilder.Entity<CampaignSurvey>().ToTable("Campaign");
modelBuilder.Entity<CampaignFeedback>().ToTable("Campaign");
}
I'm even not sure how this will work in the real scenario. You can find some other problems when using it.
Something I have found that works is to create a view and point your additional entities to that.

How to update a property of an abstract with an inheriting/using a subblass in MVC

I have an abstract class
public abstract class Member
{
public string ID { get; set; }
public string Username { get; set; }
public int MemberType { get; set; }
public abstract string MemberName { get; set; }
public int Status { get; set; }
}
public class Person : Member
{
public string LastName { get; set; }
public string FirstName{ get; set; }
}
public class Business : Member
{
public string BusinessName { get; set; }
public string TaxNo { get; set; }
}
The class was mapped using fluent API,
Now, is there a way to update the "Status" property from the view(having Member model) without using or going to a subclass (Person/Business)?
I just tried it, but it says "Cannot create an abstract class.", when submitting the page.
Or there is a correct way to do this?
Thanks
Not in EF. You have to instantiate an object to work with EF, and you can't instantiate an abstract class.
You could make the class not be abstract. Or you could use a stored proc to update the field, or some direct sql.
It sounds like your problem is that your action method has an abstract type as a parameter, which the default model binder can't do anything with. If you are dead set on using the same view for two different classes, you may need to implement your own model binder to inspect in the incoming request and decide which type, Person or Business, to instantiate.
Check out this link for more information on creating a custom model binder:
http://odetocode.com/blogs/scott/archive/2009/05/05/iterating-on-an-asp-net-mvc-model-binder.aspx
This seems like a similar problem to the one I've answered previously here:
ASP.NET MVC 3: DefaultModelBinder with inheritance/polymorphism

Resources