During JSON Serialization in .NET, is there a way to specify how "deep" the object graph you wish to go? - json.net

I have some complex object graphs, when I want to send them down to the client, I'm creating a separate DTO and serializing the objects into that. This is a pain in the ass. Is there anyway to serialize objects and only say, "Go one references deep" so if I have an object:
public class Test {
public Project { get; set; }
}
public class Project {
public int Id { get; set; }
public Vendor Vendor { get; set; }
}
If I go to serialize Test it won't go to the Vendor, but it'll correctly serialize the Project. I realize I can add an annotation for JsonIgnore, but if I were serializing all Projects, I might want a Vendor.

I think you're going to have to do some custom extension work: I found a conversation and some samples at http://json.codeplex.com/Thread/View.aspx?ThreadId=24459

Related

Ignore certain ViewModel properties in API requests?

Suppose I have the following example Resource Model defined for API Create/Read/Update/Delete interactions involving the Customer types:
public class CustomerModel
{
public string Address { get; set; }
public int Id { get; set; }
[Required]
public string Name { get; set; }
[Url]
public Uri Website { get; set; }
public DateTimeOffset WhenCreated { get; set; }
public DateTimeOffset WhenUpdated { get; set; }
}
Id, WhenCreated, and WhenUpdated are metadata to be generated by the underlying data repository and as such, if the customer adds them to a request they should not be kept (Id for example, would be specified in the URL so no need to include in the request body). However, these values are still important to the client.
Is there a simple approach to ignoring these metadata attributes if sent in the client request? I would expect this in the form of an attribute but have not found anything promising for .NET Core 3.1.
The JsonIgnore attribute would make sense but it wouldn't serialize the values in responses either.
I could create a separate model only used by clients for requests but this seems redundant, especially because it will require new mapping profiles. However, if using something like Swashbuckle for API documentation this could be the best approach since the class documentation wouldn't represent those as valid properties for requests.
I could add some logic to remove those properties in the business logic layer but that would likely involve another request to the database to retrieve their original values so it isn't ideal.
Thank you!

How can I serialize data to XML without .xsd schema?

I am writing an ASP.NET MVC (5) application in which I need to do some custom XML serialization. Before I go on, I should mention that I wasn't exactly sure if this question belongs here or on another forum. If this question would be better suited somewhere else, please let me know. I'll gladly move it.
Software overview:
I have a view that has a form for the user to fill out. When the user fills out the required fields and clicks the submit button, the information in the form should be serialized to XML (based on certain XML requirements), and posted to a URL. That's pretty simple for some, I'm sure. I have very little experience doing this sort of thing in ASP.NET MVC.
I don't possess the .xsd document that contains the XML schema. I have a document that contains the XML specifics (a Word document), but the actual .xsd document is not available to me. I am not sure how to serialize the data so that the XML turns out the way it is supposed to.
I have the following Model:
public class BookingRequest
{
public string billTo { get; set; }
public string bookingStatus { get; set; }
public string partNote { get; set; }
public int height { get; set; }
}
Note that this is an abbreviated version; there are WAY more fields in this class. Anyway, I need the height field to look like this when it is serialized to XML:
<HeightOf>15</HeightOf>
I also need all of the elements in the XML to adhere to this schema (where all of the fields in the form I mentioned fall under the <BookingRequest> tag):
<Data>
<Header>
<UserId/>
<Password/>
</Header>
<BookingRequest>
..
..
</BookingRequest>
</Data>
Can I do this without the schema?
Any help is greatly appreciated.
You don't need the xsd, as long as you know how is going to be the desired structure.
First, you need to decorate your class with the [Serializable] attribute. Then, you can use the attributes in System.Xml.Serialization namespace to control the result. For example, in case of height property, it can be achieve like this:
[Serializable]
public class BookingRequest
{
public string billTo { get; set; }
public string bookingStatus { get; set; }
public string partNote { get; set; }
[XmlElement(ElementName = "HeightOf")]
public int height { get; set; }
}
See this for further details:
https://learn.microsoft.com/en-us/dotnet/standard/serialization/controlling-xml-serialization-using-attributes

EF Code First: One-to-One One-way Relationship

I regularly have the following structure:
MyClass
public virtual ICollection<Version> Versions { get; set; }
public virtual Version CurrentVersion { get; set; }
That is, there is a list of stuff, and some class both points to that list, and one specific item in that list - either the current version of many versions, the next upcoming event in a list of events, etc.
In my schema what I'd like to end up with is a Foreign Key pointing from Version to MyClass - that much works out properly. But then I'd like a Foreign Key pointing from MyClass to Version representing the CurrentVersion property, with no Foreign Key pointing back - I don't want the extra storage or bother of telling a Version what MyClass it's the CurrentVersion for, if any. Put another way, I'd like this second relationship to be one-way from MyClass to Version, even though it's one-to-one.
What EF Code First gives me instead is the normal one-to-many on the first property, with the FK from Version to MyClass, but then a full one-to-one relationship on the second property with an FK pointing in both directions - so the underlying schema for Version ends up with MyClass_Id and MyClass_Id1.
So, is there a way to get a one-way relationship in EF Code First without resorting to the Fluent API? It looked like maybe System.ComponentModel.DataAnnotations.Schema.InverseProperty had a shot at it, but it didn't seem to offer a way to say "Don't generate one."
The key is to specify the InverseProperty on the property that points back, so that EF realizes it's to the Many-to-Many, not to the One-to-One.
public class MyClass
{
public int Id { get; set; }
public Version CurrentVersion { get; set; }
public ICollection<Version> Versions { get; set; }
}
public class Version
{
public int Id { get; set; }
[InverseProperty("Versions")]
public Versioned Versioned { get; set; }
}

Entity Framework 4.1 Code First: Advice on persisting data from external source?

Part of my project is to persist data from another source. In this case we have an SAP data source that we will need to pull data from. I need to take the data from SAP and map it to entities I have in my application. Here is an example of an entity I have in my application:
public class Project : BaseEntity
{
public string Name { get; set; }
public string ProjectNumber { get; set; }
public string Description { get; set; }
public string CreatedBy { get; set; }
public string ModifiedBy { get; set; }
public string Currency { get; set; }
#region Navigation Properties
public virtual Address Address { get; set; }
public virtual CompanyCode CompanyCode { get; set; }
public virtual ICollection<Contact> TeamMembers { get; set; }
#endregion
}
As you can see, I have child objects that I map from SAP as well. I need some advice on the best way to insert and update my entities. I am struggling with knowing when to add (insert) entities to my context and when to attach (update) them, because SAP doesn't have knowledge of what my application may or may not have. I need to guard against duplicates, too. For example, should I perform a lookup of each child entity in my parent entity to see if they exist before I apply them to the parent? Then, add / attach the entire parent object to the context or handle each entity separately while still maintaing their relationships?
Yes you must manually test everything to make correct decision what must be inserted, updated or deleted. Depending on the application you can use some more complex queries to reduce number of round trips to the database - for example you can use single query with Contains to load all TeamMembers needed for processed Project or you can load Project with including all related data if you also need to test if project exists.
I did large synchronization application before and I end up with pre-loading all entities at the beginning with few queries and working completely in memory.
Don't forget to use DbSet's Local property or Find method to take advantage of already loaded entities.
You can also use some custom stored procedures to improve performance of this operation.

How to edit a SQL Server XML data field with asp.net Dynamic Data

I have a site based around asp.net 3.5's Dynamic Data feature. Everything's working great, but I would like to add a tagging feature via a column with an XML data type. I've made the column and added an appropriate schema, but it is showing up as read-only and the scaffold will not display or modify the field.
So, I have a few questions:
What do I need to do in order to enable my scaffold to see this xml column?
How would I go about editing the tags through the scaffold without directly editing all the xml?
Would I add logic to the getter/setter in the metadata?
Presumably I would need a custom fieldTemplate, would I add the xml parsing to it?
I hope this is helpful. As you mention, you would have to create a field template for your XML data. :
[MetadataType(typeof(DocumentMetadata))]
[DisplayName("Documents")]
public partial class Document {
[ScaffoldColumn(true)]
[Display(Name = "Some Xml")]
public string SomeXml
{
get
{
return "<note><to>Joe</to><from>Mary</from><heading>Reminder</heading><body>Hello World</body></note>"
}
}
}
public class DocumentMetadata
{
[ScaffoldColumn(false)]
public object Id { get; set; }
[Display(Name="Type")]
public object DocumentType { get; set; }
[UIHint("CustomXmlFieldTemplate")]
[Display(Name="Some XML")]
public object SomeXml { get; set; }
}

Resources