I'm hooking up to a pretty extensive online service using JSON in C# and have noticed they use the same name with different values (and types).
In creating the JSON models I'm running into an issue where the different models require different value types.
For example.
namespace Mylibrary
{
// event
public class event
{
public Item item { get; set; }
public string type { get; set; }
}
public class Item
{
public string url { get; set; }
public string icon { get; set; }
}
// context
public class context
{
public Item item { get; set; }
public string creator { get; set; }
}
public class Item
{
public int index { get; set; }
public string name { get; set; }
}
}
If I rename the above item class I can no longer use the json deserializer. However, of course I get a compiler error because of the duplicate class name "Item".
There are somewhere above 30 data models that I need to generate for this service. In looking closer at their schema, this is going to be an issue for over 90% of those models. The models themselves are very large, the example above is a simplified example of what I'm running into to illustrate the problem.
In thinking about this issue, I'm betting this would be a rather common occurrence. How is this dealt with?
As #mecek points out, it's the property names that matter, not the class names. So just give the classes unique names:
EventItem
ContextItem
Then you can use JsonProperty to rename the properties:
public class Context
{
[JsonProperty("item")]
public ContextItem Item { get; set; }
[JsonProperty("creator")]
public string Creator { get; set; }
}
Related
I have a Question.
I have 2 Dto Object and one Model.
What i'm trying todo is map the AssetDTO to the Asset Model using Automapper.
I have no clue on how to accomplish this.
public class AssetDTO
{
public string Code { get; set; }
public string CodeType { get; set; }
public List<MetricDataDTO> Data { get; set; }
}
public class MetricDataDTO
{
public string Value{ get; set; }
public string Flow { get; set; }
}
I have one model that look like this.
public class Asset
{
public string Code { get; set; }
public string CodeType { get; set; }
public string Value{ get; set; }
public string Flow { get; set; }
}
I tryed setting up the mapping with automapper but without any luck :(
Hope anyone can help me out,Thanks in advance!!
if suppose the value and flow inside asset is array, I think your current model for Asset need to be change (i.e. by creating new field List<MetricData> like List<MetricDataDTO>). Later you can check this one AutoMapper - Mapping list of objects to bigger list of objects.
In case for each asset there's only one value and flow, your model for AssetDTO will become:
public class AssetDTO
{
public string Code { get; set; }
public string CodeType { get; set; }
public MetricDataDTO Data { get; set; }
}
And for such case, here the example for nested object (based on Using automapper for nested objects): https://dotnetfiddle.net/qVg59r
Below answer also much more simpler https://stackoverflow.com/a/74471904/10766263
Thanks to Lucian Bargaoanu!
If you need more control when flattening, you can use IncludeMembers. You can map members of a child object to the destination object when you already have a map from the child type to the destination type.
This allows you to reuse the configuration in the existing map for the child types MetricDataDTO when mapping the parent types AssetDTO and Asset .
It works in a similar way to mapping inheritance, but it uses composition, not inheritance.
cfg.CreateMap<AssetDTO, Asset>().IncludeMembers(s=>s.MetricDataDTO);
You can check this link for details.
https://docs.automapper.org/en/latest/Flattening.html#includemembers
Hope it can help you.
I have not worked with EF for a while.
As an exercise, I am writing a core web api that allows keeping track of a user medias.
A media can be a postcard, a photo album, a recording, a book...
I would like to know what is the way to go/best practice in writing the Add (createMedia) method:
[HttpPost]
public async Task<ActionResult<bool>> Add(Media media)
My model is comprised of several specific classes representing one type of media - like Postcard, Photoalbum, recording, etc. In addition, there is a Media type - which contains shared properties among all media types:
public class Media
{
[Key]
public int Id { get; set; }
public string Title { get; set; }
public string Description { get; set; }
public MediaType Type { get; set; }
public bool InUse { get; set; }
public string Date { get; set; } //yyyy-mm-dd
public string Owner { get; set; }
}
As an example of one of the specific media types:
public class Postcard
{
[ForeignKey("Id")]
public int MediaId { get; set; }
public string From { get; set; }
public string To { get; set; }
public string Place { get; set; }
public string Language { get; set; }
}
I designed my EntityFramework db to consist of a 1-1 relation between Media and the relevant specific media table.
What is the best practice in writing the Add method ? Should it receive a Media object, and based on MediaType create the respective type ? I started with this approach, and had the action receive a second parameter named detailsJson, which I would parse and fill the respective object using reflection, but figured out that POST binding will not bind 2 objects.
I'm not well versed in design patterns.
Should there exist as many AddBook, AddPostcard... as many media types ?
I understand all models should be POCO objects, without inheritance.
I read about DTOs, but does not see how it helps me here.
I guess the Postcard and Book although both media types, they have different properties? for example, From, To, Place fields will not be there in book, whereas Book might have ISBN, Author, Genre etc.
so essentially they are different POCO objects altogether, media type is just a relationship they have in common
In this case, it's OK to have separate Add methods like AddBook, AddPostcard etc.
Update:
The individual POCO objects can refer to Media type to avoid duplicating same properties, same as underlying entity relationship
public class Postcard
{
public Media Media { get; set; }
public string From { get; set; }
public string To { get; set; }
public string Place { get; set; }
public string Language { get; set; }
}
What about having a Key-Value table?
public class MediaValue {
public string MediaId {get;set;}
public string AttributeName {get;set;}
public string AttributeValue{get;set;}
//the key is the couple MediaId - AttributeName
}
public class Media {
//shared properties
public MediaType MediaType {get;set;}
public IEnumerable<MediaValue> Attributes {get;set;}
}
public enum MediaType {
PostCard, PhotoAlbum, ....
}
then you could add the DTOs foreach mediatype
public abstract class MediaDTO {
//shared properties
}
public class PostCardDTO : MediaDTO {
public string PostCardSpecificAttribute {get;set;} // this.PostCardCustomAttribute = aMediaDbObject.Attributes.FirstOrDefault(x => x.AttributeName == "PostCardSpecificAttribute");
}
We're attempting to build a somewhat basic reporting system for our analytics team to use. It's our third or fourth iteration of the same system, but we're doing a consolidation and rewrite of a large portion of the backend logic to make generating reports easier going forward.
One issue we're having is forming the interfaces that will be implemented by our reporting widgets in order to push them through to our ViewComponents.
An example of a couple widgets may look something like the following:
public interface IWidget<T>
{
WidgetType WidgetType { get; set; }
string WidgetName { get; set; }
T ViewModel { get; set; }
}
public class ChartWidget : IWidget<Chart>
{
public WidgetType WidgetType { get; private set; }
public string WidgetName { get; set; }
public Chart ViewModel { get; set; }
public ChartWidget() {
WidgetType = WidgetType.Chart;
}
}
public class HeadlineBarWidget : IWidget<HeadlineBarData>
{
public WidgetType WidgetType { get; private set; }
public string WidgetName { get; set; }
public HeadlineBarData ViewModel { get; set; }
public ChartWidget() {
WidgetType = WidgetType.HeadlineBar;
}
}
But the report will contain a collection of widgets, and that collection will need to be iterated over in the View in order to fetch the proper ViewComponents and supply them with the matching model that they expect. Unfortunately, it appears most collection types need to ensure type safety, and I need a way to make this a bit better. As it stands now, our IWidget object defines ViewModel as an object, and I don't think this is a good practice.
My program is starting to get pretty big. and i have found that its starting to do the same thing in multiple area's.
Im trying to figure out how i can make it more efficient.
So i have an object that looks like this
public class TreeViewNode
{
public TreeViewNode()
{
Children = new ObservableCollection<TreeViewNode>();
}
public String Name { get; set; }
public string Description { get; set; }
public ObservableCollection<TreeViewNode> Children { get; set; }
}
i also have another object that looks like this;
public class ComputerObject
{
public String Name { get; set; }
public Int32 UUID { get; set; }
public DateTime Created { get; set; }
public ObservableCollection<Object> Children { get; set; }
}
Both these items need to have some of the same properties..
at the moment they both have the Children Property and the Name Property. but they both need to have some other common properties added to them.
so i have tried something like this.
public class BaseObject
{
public String Name { get; set; }
public ObservableCollection<Object> Children { get; set; }
public string Description { get; set; }
public BaseObject()
{
Children = new ObservableCollection<object>();
}
}
public class ComputerObject: BaseObject
{
public Int32 UUID { get; set; }
public DateTime Created { get; set; }
}
public class TreeViewNode: BaseObject
{
public String IconPath { get; set; }
}
Now this is just a cut down version of what i am implementing, i have alot of objects that share the same properties. and some that dont and mix and match. and i cannot figure out the best implimentation for this.
My Objects are becoming very cluttered, and when i rename a property i find that i have to rename it in several area's and this isnt the way its ment to be.
can someone please advise how i would implement multiple objects that share the same property names?
In my opinion you should not let classes inherit from one baseclass when these childclasses are not related to each other (like #Sriram Sakthivel asked Animal < Dog,Cat) just to share the same properties.
You should determine which classes are related (cat, dog are animals; car, motorcycle are vehicles) and then create baseclasses based on these "groupings".
I would look into decorator pattern. In short, you dont share common properties via inheritance. You make classes that contain common properties, and use these classes as properties in your end classes.
EDIT: Example is actually just a standard composition, it should work nevertheless
E.G.
public class Decorator1
{
public String Name { get; set; }
public ObservableCollection<Object> Children { get; set; }
public string Description { get; set; }
}
public class Decorator2
{
public long Id { get; set; }
}
public class ClassA
{
public Decorator1 TreeNodeImpl;
}
public class ClassB
{
public Decorator1 TreeNodeImpl;
public Decorator2 LongIdImpl;
}
I've created an MVC 3 Razor application that manages Projects, and should manage Sections within those Projects.
So, I've made a model Projects.cs, controller ProjectsController, and got myself a Projects.sdf data table. Works just fine
Then I've added same for Sections, but Sections should have a field named projectID (made it of course) that is connected (joined) with ID in Projects.sdf; also, I need it to be able to be sorted by projectID, and from a DropDown
For example: Using DropDown to alter the table data. If lets say I select project1 from Project list, I want the list to show all Sections within that Project along with CRUD.
I've tried several things but none worked so far, I know how to do this in regular application but not in MVC so I beg for some assistance. Also tried to add DropDown in Sections view and getting it to populate from Project model data, but no good at all.
So I need help on how to do this :(
Please, and thank you.
Addition
Project has many Sections, and yes I'm using EF, but as I said not too experienced with it.
as for data context
this is Project
namespace MyProject.Models
{
public class Projects
{
public int ID { get; set; }
public string projectName { get; set; }
public string shortDesc { get; set; }
}
public class ProjectsDBContext : DbContext
{
public DbSet<Projects> Projects { get; set; }
}
}
this is Section
namespace MyProject.Models
{
public class Sections
{
public int ID { get; set; }
public int projectID { get; set; }
public string Name { get; set; }
public string Description { get; set; }
}
public class SectionsDBContext : DbContext
{
public DbSet<Sections> Sections { get; set; }
}
}
Addition 2
So I made a model named MyProjectModels.cs
namespace MyProject.Models
{
public class Project
{
public int ID { get; set; }
public string Name { get; set; }
public string Description { get; set; }
}
public class Section
{
public int ID { get; set; }
public int projectID { {get; set;}
public string Name { get; set; }
public string Description { get; set;}
}
}
So basically I'm kinda figuring it out. Please let me know if this is ok for models or do I need to put them in separate files? Also, How should i declare context from this point, a hint would be enough :)
Thank you
This is the way I have done it. It displays properly but i have NO idea how to utilize it, for example to show different values in a table...
<select id="select1" name="select1">
#foreach (var item in Model.Enrollments)
{
<option value=#Html.DisplayFor(modelItem => item.Course.Title)>#Html.DisplayFor(modelItem => item.Course.Title)</option>
}
</select>
by different values in table i meant, when i select different enrollment in this case. i would like to show different values in table.
Do you really need to have different dbcontexts? If it is one sdf file then I'm guessing not and your dbcontext should look like
namespace MyProject.Models
{
public class DatabaseContext: DbContext
{
public DbSet<Projects> Projects { get; set; }
public DbSet<Sections> Sections{ get; set; }
}
}
then in your projects model you would have a property for sections
namespace MyProject.Models
{
public class Projects
{
public int ID { get; set; }
public string projectName { get; set; }
public string shortDesc { get; set; }
public Sections section { get; set; }
}
}
and your sections would just need an id field
namespace MyProject.Models
{
public class Sections
{
public int ID { get; set; }
public int projectID { get; set; }
public string Name { get; set; }
public string Description { get; set; }
}
}
As long as your sections class has a primary key field called ID or the id property flagged as the primary key then EF will make the logical leap that Projects has a foreign key of section in the table structure. your projects model will then have access to the section object. Biggest hurdle I had with EF was overthinking the database side of things.
For the dropdown list here is the way I have done it
public class ChangeUserNameViewModel
{
public ChangeUserNameViewModel()
{
var user = User.GetAllButBuiltIn();
Users = new SelectList(user, "UserName", "UserName");
}
public User User
{
get;
set;
}
[DisplayName("User Name")]
public SelectList Users
{
get;
set;
}
public string UserName
{
get;
set;
}
}
then in the view I reference the viewmodel
#model ChangeUserNameViewModel
#Html.DropDownList("UserName", Model.Users, "Choose")
the first parameter is the name of the drop down in the html. the second the select list to populate it and the third the selected value. I'm sure there are better ways to do it. For example you could have an IList in your model and then do a foreach loop in your view. It all depends on what works best in your case.