How to generate code based on another class? - visual-studio

To create our test data, we use the following variation of the Builder pattern (simplified example!):
Sample class:
public class Person
{
public string Name { get; set; }
public string Country { get; set; }
}
The builder:
public class PersonBuilder
{
private string name;
private string country;
public PersonBuilder()
{
SetDefaultValues();
}
private void SetDefaultValues()
{
name = "TODO";
country = "TODO";
}
public Person Build()
{
return new Person
{
Name = name,
Country = country
};
}
public PersonBuilder WithName(string name)
{
this.name = name;
return this;
}
public PersonBuilder WithCountry(string country)
{
this.country = country;
return this;
}
}
NOTE: The context of the example itself is not relevant. The important thing here is how in the example, the a builder class like PersonBuilder can completely be generated by looking at the entity class (Person) and applying the same pattern - see below.
Now imagine that the person class has 15 properties instead of 2. It would take some monkeywork to implement the builder class, while theoretically, it could automatically be generated from the Person class. We could use code generation to quickly set up the builder class, and add custom code later if needed.
The code generation process would have to be aware of the context (name and properties of the person class), so simple text-based code generation or regex magic doesn't feel right here. A solution that is dynamic, not text-based and can be triggered quickly from inside visual studio is preferred.
I'm looking for the best way to perform code generation for scenarios like this.
Reflection? Codesmith? T4 templates? Resharper Live templates with macros?
I'm looking forward to see some great answers :)

The T4 solution is a well Visual Studio integrated option. You can use reflection inside the T4 template to actually generate the code.

We added a feature in CodeSmith Generator 5.x that allows you to generate off of existing code. Please take a look at that documentation here. Also you can use reflection or any .NET library in a CodeSmith Generator Template.
Thanks
-Blake Niemyjski

If it is for test only, consider a mocking framework like RhinoMocks:
internal class PersonBuilder
{
private MockRepository _mockRepository;
private IPerson _person;
public PersonBuilder()
{
_mockRepository = new MockRepository();
_person = _mockRepository.Stub<IPerson>();
}
public PersonBuilder WithName(string name)
{
_person.Name = name;
return this;
}
public PersonBuilder WithCountry(string Country)
{
_person.Country= Country;
return this;
}
public IPerson Build()
{
_mockRepository.ReplayAll();
return _person;
}
}
This way your builder can evolve along with your need. Further, you don't need to change your Build method. Just add "WithX" methods.

Have a look into the ABSE modeling approach and its IDE, AtomWeaver. ABSE is a template-based modeling and code generation framework, where a model (has nothing to do with UML or MDA) is created by applying "building blocks" (Atoms). These Atoms are template/program hybrids and are context-aware: an Atom can generate code according to its placement on the tree and on the presence/absence of certain Atoms.
The model host (AtomWeaver in this case) will "execute" the model in order to obtain the desired source code. The model can be "the source": change the model and regenerate as many times as necessary.
AtomWeaver is not integrated into Visual Studio, but can work alongside it without any problems.

Related

GraphQl Java, How can I blindly return all variables associated with an object from query and question on handling sub classes

I'm new to GraphQL and I'm currently implementing a GraphQL API into an established Java code, using GraphQL-SPQR and I'm running into a couple issues when it comes extracting data from hierarchical classes.
The issues that I am running into are as follows.
Firstly I don't if there is an easy way to get all the data associated with a returned node. If there is, this would be most useful for my more complex classes.
Secondly when a method returns an abstract class, I only seem able to request the variables on the abstract class. I'm sure this should be possible I am just hitting my head against a wall.
As a simple example
public abstract class Animal {
private String name;
private int age;
// Constructor
#GraphQLQuery(name = "name")
public String getName() {
return name;
}
// Age getter
}
public class Dog extends Animal {
private String favouriteFood;
// Constructor
#GraphQLQuery(name = "favouriteFood")
public String getFavouriteFood() {
return favouriteFood;
}
}
public class Database {
#GraphQLQuery(name = "getanimal")
public Animal getAnimal(#GraphQLArgument(name = "animalname") String animalname) {
return database.get(name);
}
}
So in my first question what I am currently querying is.
"{animalname(name: \"Daisy\") {name age}}"
This works fine as expected. If you imagine the class however had 10 variables I would like to merely be able to write the equivalent of the following without having to look them up.
"{node(name: \"Daisy\") {ALL}}"
Is this possible?
In terms of my second question.
The follow query, throws an error ('Field 'favouriteFood' in type 'Animal' is undefined')
"{animalname(name: \"Bones\") {name age favouriteFood}}"
likewise (reading Inline Fragments of https://graphql.org/learn/queries/)
"{animalname(name: \"Bones\") {name age ... on Dog{favouriteFood}}}"
throws an error Unknown type Dog
This is annoying as I have a number of sub classes which could be returned and may require handling in different fashions. I think I can understand why this is occuring as GraphQL has no knowledge as to what the true class is, only the super class I have returned. However I'm wondering if there is a way to fix this.
Ultimately while I can get past both these issues by simply serialising all the data to JSON and sending it back, it kind of gets rid of the point of GraphQL and I would rather find an alternate solution.
Thank you for any response.
Apologies if these are basic questions.
Answering my own question to help anyone else who has this issue.
The abstract class needs to have #GraphQLInterface included, as shown below
#GraphQLInterface(name = "Animal ", implementationAutoDiscovery = true)
public abstract class Animal {
private String name;
private int age;
// Constructor
#GraphQLQuery(name = "name")
public String getName() {
return name;
}
// Age getter
}
The following code was found after much solution and was created by the creator of SPQR. Effectively, when setting up your schema you need to declare an interface mapping strategy. The code below can be copied wholesale with only the "nodeQuery" variable being replaced with the service you are using to containing your "#GraphQLQuery" and "#GraphQLMutation" methods.
final GraphQLSchema schema = new GraphQLSchemaGenerator()
.withInterfaceMappingStrategy(new InterfaceMappingStrategy() {
#Override
public boolean supports(final AnnotatedType interfase) {
return interfase.isAnnotationPresent(GraphQLInterface.class);
}
#Override
public Collection<AnnotatedType> getInterfaces(final AnnotatedType type) {
Class clazz = ClassUtils.getRawType(type.getType());
final Set<AnnotatedType> interfaces = new HashSet<>();
do {
final AnnotatedType currentType = GenericTypeReflector.getExactSuperType(type, clazz);
if (supports(currentType)) {
interfaces.add(currentType);
}
Arrays.stream(clazz.getInterfaces())
.map(inter -> GenericTypeReflector.getExactSuperType(type, inter))
.filter(this::supports).forEach(interfaces::add);
} while ((clazz = clazz.getSuperclass()) != Object.class && clazz != null);
return interfaces;
}
}).withOperationsFromSingleton(nodeQuery)// register the service
.generate(); // done ;)
graphQL = new GraphQL.Builder(schema).build();
As this solution took some hunting, I'm going to start a blog soon with the other solutions I've stumbled on.
With regards to having a query that just returns all results. This is not possible in GraphQL. One workaround I might write is to have a endpoint that returns JSON of the entire object and the name of the object, then I can just use ObjectMapper to convert it back.
I hope this helps other people. I'm still looking into an answer for my first question and will update this post when I find one.

Entity Framework, Ninject dependency injection, and ASP.NET MVC 3, with existing .MDF file as database

I'm making a long and detailed post here, but I sincerely believe it's better to provide as much info up front. If any further clarification is needed, please ask. My heartfelt thanks to you for reading my query.
I'm using the book Pro ASP.NET MVC3 Framework by Adam Freeman and Steven Sanderson (Apress, Third Edition), and working through the Sports Store example beginning with Chapter VII. Note that the project entails the use of DI through the use of Ninject, and this is the main reason I wanted to take the time for this walkthrough. Another impressive contribution in this tutorial is the fact that it shows you how to develop an MVC 3 solution into separate projects the way it might be done in in a real world implementation--a thing I've found to be lacking in just about every other book I've ever looked at. (BTW I think the Apress books are just about the best ones out there, generally speaking.)
OK, so I've worked through Chapter 7 and well into Chapter 8, which means that I've successfully created and populated a database and retrieved its contents to appear in my List view. I've also gotten the formatting to work through the .css file. However, there's a catch here: When going through this the first time, I created the database from the IDE itself, which was no problem because there's only one small table (Products) to worry about. Everything was working fine. But then, for reasons I will shortly make clear, I decided to start over. This time, I wanted to follow through the same walkthrough with the exception that I would access the data by attaching to an existing .MDF file rather than creating a new DB from scratch as I coded the project. All this is to pave the way for me to use a similar pattern for my real project, for which I already have built a complex DB, replete with tables, FK relationships, views, functions--and data. I hardly need to say that I want to use my existing database in my "real" project, because recreating all that from scratch would be virtually impossible.
OK, now let's return to the Sports Store example. Try as I might, I cannot get the data from the database to my UI view. There are no error messages at compile time or run time, but instead of seeing the data in the List view, I see nothing but a blank page. Note that in this case it's correct in that there are no column headings or panes because there isn't any scaffolding here.
As far as I can see I have all the parts I need. Let's begin with the Ninject controller factory:
NinjectControllerFactory : DefaultControllerFactory
{
private IKernel ninjectKernel;
public NinjectControllerFactory()
{
ninjectKernel = new StandardKernel();
AddBindings();
}
protected override
IController GetControllerInstance
(RequestContext requestContext, Type controllerType)
{
return controllerType == null ? null
: (IController)ninjectKernel.Get(controllerType);
}
private void AddBindings()
{
//Had the mockup here before, which worked fine.
ninjectKernel.Bind<IProductRepository>().To<SportsStore2.Domain.Concrete.EFProductRepository>();
} ...
}
IProductRepository is as follows:
namespace SportsStore2.Domain.Abstract
{
public interface IProductRepository
{
IQueryable<Product> Products { get; }
}
}
And EFProductRepository is implemented thus:
namespace SportsStore2.Domain.Concrete
{
public class EFProductRepository:IProductRepository
{
private EFDbContext context = new EFDbContext();
public IQueryable<Product> Products
{
get { return context.Products; }
}
}
}
Why yes, of course EFDbContext is defined; viz the declaration:
namespace SportsStore2.Domain.Concrete
{
class EFDbContext : DbContext
{
public DbSet<Product> Products { get; set; }
}
}
And the connection string in Web.config file; this is supposed to wire up the context object definition with the actual database in the .MDF file, at least as I understand it.
<connectionStrings>
<add name="EFDbContext"
connectionString="Data Source=Owner-PC\SQLEXPRESS;Initial Catalog = SportsStore20130205; Integrated security=SSPI"
providerName="System.Data.SqlClient" />
</connectionStrings>
Last and almost certainly least, I have the Product controller defined as follows. I say "least" because I'm almost positive the problem isn't here. In Debug mode, I can tell that the productRepository object isn't being populated. I can see some SQL code in there which is supposed to be run, or have been run by this point. But the invocation of repository.Products returns nothing.
namespace SportsStore2.WebUI.Controllers
{
public class ProductController : Controller
{
private IProductRepository repository;
public ProductController(IProductRepository productRepository)
{
repository = productRepository;
}
public ViewResult List()
{
return View(repository.Products);
}
public ViewResult Count()
{
int counter = repository.Products.Count();
return View(repository.Products.Count());
}
}
}
namespace SportsStore2.WebUI.Controllers
{
public class ProductController : Controller
{
private IProductRepository repository;
public ProductController(IProductRepository productRepository)
{
repository = productRepository;
}
public ViewResult List()
{
return View(repository.Products);
}
}
}

View and Domain model, where to perform calculation

I just started using View & Domain model design in my MVC web app but got the question where to perform calculations and other View related actions. I will try to give example below.
My Domain Model (Linq2Sql)
public class Product
{
public int Id;
public string Name;
}
The View Model with new UserCount property which I would like to calculate.
public class ProductViewModel
{
public int Id;
public string Name;
public int UserCount;
}
My controller action looks like
public ActionResult _SelectionClientSide_Products()
{
IQueryable<Product> products = _repository.GetProducts(true);
var model = Mapper.Map<IEnumerable<Product>, IEnumerable<ProductViewModel>>(products);
return View(model);
}
I query for data using repository method and get IQueryable<Product> and map it to ProductViewModel list. But I also need to perform another query operation to count users for every queried product and assign all values to ProductViewModel. What design I should follow to achieve this?
The relationship between tables
Products -> Orders - > Users
EDIT
I have decided to remove AutoMapper because it gives more problems than benefits and created my own Builder which contain everything what I need. I make field assign and also add calculation.
public ActionResult _SelectionClientSide_Products()
{
Data = new ProductViewModelBuilder(_repository).Build();
return View(Data);
}
namespace PC.Models
{
public class ProductViewModel
{
public int Id { get; set; }
public string Name { get; set; }
public int UsersCount { get; set; }
}
public class ProductViewModelBuilder
{
private readonly IDataAccess _repository;
public ProductViewModelBuilder(IDataAccess repository)
{
_repository = repository;
}
public IQueryable<ProductViewModel> Build()
{
return _repository.GetProducts().Select(p=> new ProductViewModel
{
Id = p.Id,
Name = p.Name,
UsersCount = _repository.CountUsers(p.Id)
});
}
}
}
In my opinion, by the time your Controller has begun it's model setup, there should be no more "logic" or talking to the model. Having a "builder" which queries the model again is bad practice. Not really "breaking" the MVC pattern, but still bad practice. Your ViewModel has a dependency on your DAL. Bad bad boy. :)
If you have to run another query, well that should be encapsulated in the original query. Instead of calling _repository.GetProducts, call a different method which not only gets the products, but get's the count as well. Create a DTO if necessary.
Then your controller should look like:
public ActionResult _SelectionClientSide_Products()
{
var someDto = _repository.GetProductsAndUserCount(true);
var model = Mapper.Map<IEnumerable<SomeDto>, IEnumerable<ProductViewModel>>(someDto);
return View(model);
}
Personally i go for generic repositories over specialized ones, as i don't want a IProductRepository interface with 50 signatures. I opt for LINQ IEnumerable<T> extensions (aka "pipes and filters") which allows complex queries to be built and remain in my domain.
So my version of the above would be:
public ActionResult _SelectionClientSide_Products()
{
var someDto = _productRepository.Find().WithSomeCondition(true).ToSomeDto();
var model = Mapper.Map<IEnumerable<SomeDto>, IEnumerable<ProductViewModel>>(someDto);
return View(model);
}
On a side note, why do you say AutoMapper causes you more problems that benefits? AutoMapper has saved me tons and tons of repetitive code. If you know how to use it properly, it's your best friend. Hands down the most important NuGet package in my current application.

EF and repository pattern - ending up with multiple DbContexts in one controller - any issues (performance, data integrity)?

Most of my knowledge of ASP.NET MVC 3 comes from reading through the book Pro ASP.NET MVC 3 Framework by Adam Freeman and Steven Senderson. For my test application I have tried to stick to their examples very closely. I am using the repository pattern plus Ninject and Moq which means that unit testing work quite well (i.e. without needing to pull data from the database).
In the book repositories are used like this:
public class EFDbTestChildRepository
{
private EFDbContext context = new EFDbContext();
public IQueryable<TestChild> TestChildren
{
get { return context.TestChildren; }
}
public void SaveTestChild(TestChild testChild)
{
if (testChild.TestChildID == 0)
{
context.TestChildren.Add(testChild);
}
else
{
context.Entry(testChild).State = EntityState.Modified;
}
context.SaveChanges();
}
}
And here is the DbContext that goes with it:
public class EFDbContext : DbContext
{
public DbSet<TestParent> TestParents { get; set; }
public DbSet<TestChild> TestChildren { get; set; }
}
Please note: to keep things simple in this extracted example I have left out the interface ITestChildRepository here which Ninject would then use.
In other sources I have seen a more general approach for the repository where one single repository is enough for the whole application. Obviously in my case I end up with quite a list of repositories in my application - basically one for each entity in my domain model. Not sure about the pros and cons about the two approaches - I just followed the book to be on the safe side.
To finally get to my question: each repository has its own DbContext - private EFDbContext context = new EFDbContext();. Do I risk ending up with multiple DbContexts within one request? And would that lead to any significant performance overhead? How about a potential for conflicts between the contexts and any consequences to the data integrity?
Here is an example where I ended up with more than one repository within a controller.
My two database tables are linked with a foreign key relationship. My domain model classes:
public class TestParent
{
public int TestParentID { get; set; }
public string Name { get; set; }
public string Comment { get; set; }
public virtual ICollection<TestChild> TestChildren { get; set; }
}
public class TestChild
{
public int TestChildID { get; set; }
public int TestParentID { get; set; }
public string Name { get; set; }
public string Comment { get; set; }
public virtual TestParent TestParent { get; set; }
}
The web application contains a page that allows the user to create a new TestChild. On it there is a selectbox that contains a list of available TestParents to pick from. This is what my controller looks like:
public class ChildController : Controller
{
private EFDbTestParentRepository testParentRepository = new EFDbTestParentRepository();
private EFDbTestChildRepository testChildRepository = new EFDbTestChildRepository();
public ActionResult List()
{
return View(testChildRepository.TestChildren);
}
public ViewResult Edit(int testChildID)
{
ChildViewModel cvm = new ChildViewModel();
cvm.TestChild = testChildRepository.TestChildren.First(tc => tc.TestChildID == testChildID);
cvm.TestParents = testParentRepository.TestParents;
return View(cvm);
}
public ViewResult Create()
{
ChildViewModel cvm = new ChildViewModel();
cvm.TestChild = new TestChild();
cvm.TestParents = testParentRepository.TestParents;
return View("Edit", cvm);
}
[HttpPost]
public ActionResult Edit(TestChild testChild)
{
try
{
if (ModelState.IsValid)
{
testChildRepository.SaveTestChild(testChild);
TempData["message"] = string.Format("Changes to test child have been saved: {0} (ID = {1})",
testChild.Name,
testChild.TestChildID);
return RedirectToAction("List");
}
}
catch (DataException)
{
//Log the error (add a variable name after DataException)
ModelState.AddModelError("", "Unable to save changes. Try again, and if the problem persists see your system administrator.");
}
// something wrong with the data values
return View(testChild);
}
}
It's not enough to have an EFDbTestChildRepository available but I also need an EFDbTestParentRepository. Both of them are assigned to private variables of the controller - and voila, it seems to me that two DbContexts have been created. Or is that not correct?
To avoid the issue I tried using EFDbTestChildRepository to get to the TestParents. But that obviously will only bring up those that are already hooked up to at least one TestChild - so not what I want.
Here is the code for the view model:
public class ChildViewModel
{
public TestChild TestChild { get; set; }
public IQueryable<TestParent> TestParents { get; set; }
}
Please let me know if I forgot to include some relevant code. Thanks so much for your advice!
There won't be a performance problem (unless we are talking about nanoseconds, instantiating a context is very cheap) and you won't have damaged your data integrity (before that happens you'll get exceptions).
But the approach is very limited and will work only in very simple situations. Multiple contexts will lead to problems in many scenarios. As an example: Suppose you want to create a new child for an existing parent and would try it with the following code:
var parent = parentRepo.TestParents.Single(p => p.Id == 1);
var child = new Child { TestParent = parent };
childrenRepo.SaveTestChild(child);
This simple code won't work because parent is already attached to the context inside of parentRepo but childrenRepo.SaveTestChild will try to attach it to the context inside of childrenRepo which will cause an exception because an entity must not be attached to another context. (Here is actually a workaround because you could set the FK property instead of loading the parent: child.TestParentID = 1. But without a FK property it would be a problem.)
How to solve such a problem?
One approach could be to extend the EFDbTestChildRepository by a new property:
public IQueryable<TestParent> TestParents
{
get { return context.TestParents; }
}
In the example code above you could then use only one repository and the code would work. But as you can see, the name "EFDbTest Child Repository" doesn't really fit anymore to the purpose of the new repository. It should be now "EFDbTest ParentAndChild Repository".
I would call this the Aggregate Root approach which means that you create one repository not for only one entity but for a few entities which are closely related to each other and have navigation properties between them.
An alternative solution is to inject the context into the repositories (instead of creating it in the repositories) to make sure that every repository uses the same context. (The context is often abstracted into a IUnitOfWork interface.) Example:
public class MyController : Controller
{
private readonly MyContext _context;
public MyController()
{
_context = new MyContext();
}
public ActionResult SomeAction(...)
{
var parentRepo = new EFDbTestParentRepository(_context);
var childRepo = new EFDbTestChildRepository(_context);
//...
}
protected override void Dispose(bool disposing)
{
_context.Dispose();
base.Dispose(disposing);
}
}
This gives you a single context per controller you can use in multiple repositories.
The next step might be to create a single context per request by dependency injection, like...
private readonly MyContext _context;
public MyController(MyContext context)
{
_context = context;
}
...and then configuring the IOC container to create a single context instance which gets injected into perhaps multiple controllers.
Do I risk ending up with multiple DbContexts within one request?
Yes. Each instance of a repository is going to instantiate its own DbContexts instances. Depending on the size and use of the application, this may not be a problem although it is not a very scalable approach. There are several ways of handling this though. In my web projects I add the DbContext(s) to the Request's Context.Item collection, this way it is available to all classes that require it. I use Autofac (similar to Ninject) to control what DbContexts are created within specific scenarios and how they are stored, e.g. I have a different 'session manager' for a WCF context to the one for a Http context.
And would that lead to any significant performance overhead?
Yes, but again not massively if the application is relatively small. As it grows though, you may notice the overhead.
How about a potential for conflicts between the contexts and any
consequences to the data integrity?
One of the reasons for using an ORM like this is so that changes can be maintained within the DbContext. If you are instantiating multiple context instances per request you lose this benefit. You wouldn't notice conflicts or any impact of the integrity per se unless you were handling a lot of updates asynchronously.
As promised I post my solution.
I came across your question because I was having trouble with the IIS application pool memory growing beyond limits and having multiple DBContexts was one of my suspects. In retrospect it is fair to say that there were other causes for my trouble. However, it challenged me to find a better layer based design for my repository.
I found this excellent blog: Correct use of Repository and Unit Of Work patterns in ASP.NET MVC leading me to the right direction. The redesign is based on the UnitOfWork pattern. It enables me to have just one constructor parameter for all my controllers instead of "never ending constructor parameters". And after that, I was able to introduce proactive caching as well, which solved a great deal of the earlier mentioned trouble I was having.
Now I only have these classes:
IUnitOfWork
EFUnitOfWork
IGenericRepository
EFGenericRepository
See the referred blog for complete information and implementation of these classes. Just to give an example, IUnitOfWork contains repository definitions for all entities that I need, like:
namespace MyWebApp.Domain.Abstract
{
public interface IUnitOfWork : IDisposable
{
IGenericRepository<AAAAA> AAAAARepository { get; }
IGenericRepository<BBBBB> BBBBBRepository { get; }
IGenericRepository<CCCCC> CCCCCRepository { get; }
IGenericRepository<DDDDD> DDDDDRepository { get; }
// etc.
string Commit();
}
}
The Dependency Injection (DI) is just one statement (I use Ninject):
ninjectKernel.Bind<IUnitOfWork>().To<EFUnitOfWork>();
The Controllers-constructors are maintainable:
public class MyController : BaseController
{
private MyModel mdl = new MyModel();
private IUnitOfWork _context;
public MyController(IUnitOfWork unitOfWork)
{
_context = unitOfWork;
// intialize whatever needs to be exposed to the View:
mdl.whatever = unitOfWork.SomeRepository.AsQueryable();
}
// etc.
Within the Controller I can use _context to access all repositories, if needed. The nice part of it, is that it needs just a single Commit()-call to save changed data for all repositories:
_context.Commit();

Serializing EF4.1 Entities using JSON.Net

I am building an application using MVC3, Razor view engine, Repository Pattern with Unit of Work and using EF4.1 Code First to define my data model.
Here is a bit of background (gloss over it if you want).
The application itself is just an Intranet 'Menu'.
The 2 main entities are MenuItem and Department of which:
MenuItem can have many Departments
Departments can have many MenuItems
MenuItem may have a MenuItem as a parent
This is how I have defined my Entities
public class MenuItem
{
public int MenuItemId { get; set; }
public string Name { get; set; }
public string Url { get; set; }
public virtual ICollection<Department> Departments { get; set; }
public int? ParentId { get; set; }
public virtual MenuItem ParentMenuItem { get; set; }
}
public class Department
{
public int DepartmentId { get; set; }
public string Name { get; set; }
public virtual ICollection<MenuItem> MenuItems { get; set; }
}
I am using the FluentAPI to define the Self Reference Many-to-Many for the MenuItem.
The issue I am having is passing a MenuItem to the view via JSON.
The central issues are that I have a circular reference between my entities that the built in JSON parser can't deal with and I have lazy loading and proxy generation still enabled.
I am using JSON.net library from Nuget as my JSON Serializer as this seems to be a nice way round the circular reference issue. I now am unsure how to 'fix' the proxy generation issue. Currently the serializer throws The RelationshipManager object could not be serialized. This type of object cannot be serialized when the RelationshipManager belongs to an entity object that does not implement IEntityWithRelationships.
Can anyone help me with this? If I turn off proxy generation, I am going to have a hell of a time loading all of the MenuItem children so I am keen leave this on. I have read a fair amount and there seems to be a variety of different answers including projecting the entities into another object and serialize that, etc, etc. Ideally there would be some way of configuring JSON.net to ignore the RelationshipManager object?
Update
Here is what I have used as a Custom ContractResolver for JSON.Net serializer. This seems to have sorted out my issue.
public class ContractResolver : DefaultContractResolver
{
private static readonly IEnumerable<Type> Types = GetEntityTypes();
private static IEnumerable<Type> GetEntityTypes()
{
var assembly = Assembly.GetAssembly(typeof (IEntity));
var types = assembly.GetTypes().Where(t => String.Equals(t.Namespace, "Namespace", StringComparison.Ordinal));
return types;
}
protected override List<MemberInfo> GetSerializableMembers(Type objectType)
{
if (!AllowType(objectType))
return new List<MemberInfo>();
var members = base.GetSerializableMembers(objectType);
members.RemoveAll(memberInfo => (IsMemberEntityWrapper(memberInfo)));
return members;
}
private static bool AllowType(Type objectType)
{
return Types.Contains(objectType) || Types.Contains(objectType.BaseType);
}
private static bool IsMemberEntityWrapper(MemberInfo memberInfo)
{
return memberInfo.Name == "_entityWrapper";
}
}
IEntity is an interface all my Code First entity objects implement.
I realise this question has an accepted answer, but I thought I would post my EF Code First solution for future viewers. I was able to get around the error message with the contract resolver below:
class ContractResolver : DefaultContractResolver
{
protected override List<System.Reflection.MemberInfo> GetSerializableMembers(Type objectType)
{
if (objectType.Namespace.StartsWith("System.Data.Entity.Dynamic"))
{
return base.GetSerializableMembers(objectType.BaseType);
}
return base.GetSerializableMembers(objectType);
}
}
This works because EF Code First classes inherit from the POCO class that you actually want serialized, so if we can identify when we are looking at an EF generated class (by checking the namespace) we are able to just serialize using the properties from the base class, and therefore only serialize the POCO properties that we were really after in the first place.
Well, you used powerful serialization API which serializes references and all members as well and now you complains that it serializes all members :)
I didn't test it but I believe this will bring you close to the solution.
JSON.NET is quite powerful tool and it should offer you the extensibility point to avoid this behavior but you will have to code it yourselves. You will need custom DataContractResolver where you define which members should be serialized. Here is the similar example for NHibernate.
You can implement some logic which will take only members present in the parent class of dynamic proxy. I hope this will not break lazy loading. To validate that current entity is proxy you can use this code to get all known proxy types:
IEnumerable<Type> types = ((IObjectContextAdapter)dbContext).ObjectContext.GetKnownProxyTypes();

Resources