So I have a class with a static method that uses EF to retrieve certain set of mailing lists and maps to the class.
public static List<MailingList> GetMailingListsForUser(IUsersAccess user, IProspectorDataSource db )
{
return db.MailingLists.Where(x => x.UserID == user.UserID).ToList()
.Select(y => new MailingList(y, db) ).ToList();
}
Now though I have a proc that will return the MailingList plus some extra stuff. I don't want to add these extra columns (which will be used in other sections and areas of functionality) to this class. What is the best way to address this?
I am thinking a Factory Pattern that will generate a different class that implements different contracts (interfaces) based on whats needed. Going to try implement it and will post code/working when completed.
Was wondering what other people have done in instances like this and if there are any better ways to address this.
Edit: (some extra information to help people understand what I mean).
public class MailingList
{
public int MailingListID { get; set; }
public string Name { get; set; }
public string Comments { get; set; }
public List<string> Tags { get; set; }
public int UserID { get; set; }
public System.DateTime DateCreated { get; set; }
public string CreatedBy { get; set; }
public System.DateTime LastModified { get; set; }
public string ModifiedBy { get; set; }
public List<MailingListAddress> MailingListAddresses { get; set; }
That is the definition of an object that we return. Now there is a new instance where I am going to return some extra columns from a proc and map to MailingList. So I could just add the properties to here but the issue is MailingListAddresses will be null as they will not be returned by the stored proc. So is there a way to map to specific properties and not have to return null for MailingListAddresses to the front end every time.
This was fixed by a senior developer who ended up going with the factory pattern. I will add the code when I get back to work :)
I'm trying to build simple API for training, in my database I got users (firstname, lastname, email password, list<sports>) and sports ( name, userID).
All is okay when I want to get my users, I got an object populated with sports. But the JSON response is incomplete, it is "cut" in the middle.
[{"firstName":"Nicolas","lastName":"Bouhours","email":"n.bouh#test.com","password":"nico#hotmail.fr","sports":[{"name":"Trail","userId":1
This is my controller :
// GET: api/Users
[HttpGet]
public IEnumerable<User> GetUsers()
{
var users = _context.Users.Include(u => u.Sports).ToList();
return users;
}
And my models :
public class Sport : BaseEntity
{
public string Name { get; set; }
public int UserId { get; set; }
public User User { get; set; }
}
public class User : BaseEntity
{
public String FirstName { get; set; }
public String LastName { get; set; }
public String Email { get; set; }
public String Password { get; set; }
public List<Sport> Sports { get; set; }
}
public class SportAppContext : DbContext
{
public SportAppContext(DbContextOptions<SportAppContext> options) : base(options)
{ }
public DbSet<User> Users { get; set; }
public DbSet<Sport> Sports { get; set; }
}
I really don't understand what happen, if you have any idea
I'm running into the same issue right now. You can also change the JSON serialization/configuration settings to ignore self-reference loops, as shown in the accepted answer for this question
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc().AddJsonOptions(options => {
options.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
});
}
I had this problem to in one of my projects. This is caused by a self referencing loop.
You need to create some sort of DTO (Data Transfer Object) which will be used to generate your JSON.
In your DTO you remove the inverse relationship so you end up having something like
public class SportDto
{
public string Name { get; set; }
}
public class UserDto
{
public String FirstName { get; set; }
public String LastName { get; set; }
public String Email { get; set; }
public String Password { get; set; }
public List<SportDto> Sports { get; set; }
}
You then map your user User and Sport models to your UserDto and SportDto
A good tool for doing this mapping is AutoMapper. You can read the docs to see how to get started.
After the mapping is done, you Send the DTOs as your JSON and not your models.
Just to add another yet unique scenario where this can occur. This can also happen if your DAL is returning queryables. In my scenario, I was returning a boxed object from the DAL and had something like this as a linq query
...
RootLevelProp1 = "asd",
RootLevelProp2 = "asd",
Trades = b.Trades.OrderBy(c => c.Time).Select(c => new
{
c.Direction,
c.Price,
c.ShareCount,
c.Time
}) //<---- This was being returned as a queryable to the controller
The Trades query was never being executed even though it's root object had .ToListAsync() called on it. What was happening was that the controller would return the result but only up to the Trades section and the Json would not be terminated properly. I then realized an exception was being caught in some custom middleware I wrote in which it was complaining about the data reader already being open. Without going to deep into my investigation, I assumed it had to do something with the DI and how it was handling the lifecycle of the context. The fix was to just add ToList on the trades. It's an ugly way to pass data from the DAL but this is just a fun project.
In my case this solve my issue on core 3, by using Newtonsoft:
https://learn.microsoft.com/en-us/aspnet/core/web-api/advanced/formatting?view=aspnetcore-3.0#add-newtonsoftjson-based-json-format-support
Prior to ASP.NET Core 3.0, the default used JSON formatters
implemented using the Newtonsoft.Json package. In ASP.NET Core 3.0 or
later, the default JSON formatters are based on System.Text.Json.
Support for Newtonsoft.Json based formatters and features is available
by installing the Microsoft.AspNetCore.Mvc.NewtonsoftJson NuGet
package and configuring it in Startup.ConfigureServices.
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers()
.AddNewtonsoftJson();
}
The selected answer was correct in my case as well, my JSON response was getting truncated by a reference loop in my JSON response, and setting ReferenceLoopHandling.Ignore did indeed solve my issue. However, this is not the best solution in my opinion, as this maintains the circular references in your model. A better solution would use the [JsonIgnore] attribute within the model.
The issue in your model is here:
public class Sport : BaseEntity
{
public string Name { get; set; }
public int UserId { get; set; }
public User User { get; set; } //This is the cause of your circular reference
}
public class User : BaseEntity
{
public String FirstName { get; set; }
public String LastName { get; set; }
public String Email { get; set; }
public String Password { get; set; }
public List<Sport> Sports { get; set; }
}
As you can see, your User navigation property is where this response is truncated. Specifically, it will cause each Sport in the json response to contain all of the user information for each sport entry in the response. Newtonsoft does not like this. The solution is to simply [JsonIngore] the navigation properties that cause this circular reference. In your code this would be:
public class Sport : BaseEntity
{
public string Name { get; set; }
public int UserId { get; set; }
[JsonIgnore]
public User User { get; set; } //fixed
}
public class User : BaseEntity
{
public String FirstName { get; set; }
public String LastName { get; set; }
public String Email { get; set; }
public String Password { get; set; }
public List<Sport> Sports { get; set; }
}
Faced similar issue, response was getting truncated. Issue was a getter method which trying to formatting date.
I am creating some view models for my ASP MVC web app.
I created "code first" models for database. Is it a good way to derive view models from database models?
Example database model:
public class Project
{
[Key]
public int Id { get; set; }
public int? CustomerId { get; set; }
public int TypeId { get; set; }
public string Number { get; set; }
public string Name { get; set; }
}
View model:
public class ViewModelProject : Project
{
[NotMapped]
public DateTime? Start { get; set; }
[NotMapped]
public DateTime? End { get; set; }
[NotMapped]
public string Manager { get; set; }
}
Is this the right way or is it completely false?
EDIT (subquestion):
I have some very simple database models like ProjectType, which only contains i.e. two properties. Should I also fragment those models in model view or can I make it that way:
Simple database model:
public class ProjectType
{
[Key]
public int Id { get; set; }
public string Name { get; set; }
public int? Code { get; set; }
}
Can I use it like so:
public class ProjectVM
{
public string Name { get; set; }
public int Number { get; set; }
public ProjectType Type { get; set; }
}
Or does it have to be fragmented like so:
public class ProjectVM
{
public string Name { get; set; }
public int Number { get; set; }
public string Type { get; set; }
public int TypeCode { get; set; }
}
I would not recommend doing it this way. I (and many others) have tried it and it doesn't work well. You will inadvertedly run into troubles, since an MVC model has to be tailored to the view and what you get from the DB rarely fits. Sure, you can hammer it into place, but the code quickly gets messy and store-related and UI code starts to mangle together. This even shows in your example, since you have to put the NotMappedAttribute (which is related to data storage), to ViewModelProject (a class at UI level).
There are many other examples to show this problem, but an especially good one I find when you want to serialize a model object to JSON and send it to a JavaScript client. The JSON serializer takes the values of all public properties and adds them to the JSON. If you want to exclude a property, you have to mark it with a ScriptIgnoreAttribute, which you would also have to apply to the base class, which breaks separation between UI and store-related code.
The better way to go is to keep the staorage model and the MVC model separated and to map the data from one to the other (there are already pre-existing frameworks that help you with that, such as Automapper). This comes with additional advantages, for example better testability, since you are now not dependent on a specific data store to create model instances.
I don't know how to phrase this question properly but basically I haven an ASP.Net Application. I send the following request to the controller from my view:
http://localhost:59112/Contacts/IndexJson?current=1&rowCount=50&sort%5BLastName%5D=desc&searchPhrase=&_=1490960196673
I have written two classes that are not working 100% as follows for a structure for this request data:
public class RequestData
{
public int current { get; set; }
public int rowCount { get; set; }
public string searchPhrase { get; set; }
public IEnumerable<SortData> sortItems { get; set; }
}
public class SortData
{
public string Field { get; set; } // FIeld Name
public string Type { get; set; } // ASC or DESC
}
Then in my controller I have the following:
public JsonResult IndexJson(RequestData model)
{
/* Irrelevant code */
}
The model works and fills everything correctly except the sortItems returns null. How can I get the sortItems Field and Type defined in my class?
Since the parameter coming in from the RequestData is sort[Field]=Type.
Edit
I changed my RequestData class to this:
public class RequestData
{
public int current { get; set; }
public int rowCount { get; set; }
public Dictionary<string, string> sort { get; set; }
public string searchPhrase { get; set; }
public Guid id { get; set; }
}
Now the model holds the sort as {[Field, Type]} (an example of data).
If this is a good practice, how to I access Field and Type?
You can achieve this a number of different ways; your problem in each case was simply not following the modelbinder conventions for that data type.
First and foremost, IEnumerable is out if you intend to post back to it. It's not an indexable type, so the modelbinder will never be able to bind to it. However, using something like List instead, is just fine. Then, your param names simply need to be in the format of: ListProperty[N].Property, where N is the index. So for your situation you could have used sortItems[0].Field=LastName&sortItems[0].Type=desc, and it would have bound just fine to your model.
For using a dictionary, your names should be in the format of DictionaryProperty[N].Key and DictionaryProperty[N].Value, where again, N is the index. In your scenarion that would look like sort[0].Key=LastName&sort[0].Value=desc.
We are currently in the mix of migrating from Fluent NHibernate to MongoDB. I was curious what might be the best way to go about modeling my objects. For the most part I wanted to leave them alone, but that may not be possible. For example I have these two classes:
public class Config
{
public int Id { get; set; }
public virtual string Name { get; set; }
public Filter Filter { get; set; }
}
public class Filter
{
public int Id { get; set; }
public virtual string Name { get; set; }
}
Now I understand I have to go with using Guid/string for Id when it comes to MongoDB. That's no problem. I have AutoMapper changing that over for me when I migrate the data. My concern is the data model. Clearly when I store a Config as a document in MongoDB, I don't want to store the full Filter object along with it, because there is a one-to-many relation there. Storing that Filter with it would store redundant data. Is there way via MongoDB mapping to say store the Filter Id only instead of the whole object? Using Fluent NHibernate I'm able to get this to map properly using those objects above. I'm hoping I'm just missing something.
EDIT:
I should mention that an obvious solution would be to adjust the Config class like:
public class Config : Entity
{
private string _filterId;
public int Id { get; set; }
public virtual string Name { get; set; }
public string FilterId
{
get
{
if (Filter == null)
return null;
_filterId = Filter.Id;
return _filterId;
}
set { _filterId = value; }
}
public Filter Filter
{
get
{
// return code to grab Filter by _filterId from mongo
}
}
}
However that feels dirty and inelegant to me. Is there something better?