Entity Framework Code First using context in Controller - c#

I finally got my code to work as intended but I cant figure out why the previous way I had it setup didn't work. I kept getting a null reference exception, specifically, "Object reference not set to an instance of an object.. What I want to do is to pass in a readonly BlogDb model and use the LINQ queries throughout the controller, but it seems like every controller action I have to pass in the BlogDb model.
private readonly BlogDb model;
public PostsController(BlogDb model)
{
this.model = model;
}
public ActionResult Index()
{
return View();
}
[ValidateInput(false)]
public ActionResult Update(int? id, string title, string body, DateTime date, string tags)
{
var _db = new BlogDb();
if (!IsAdmin)
{
RedirectToAction("Index");
}
if (ModelState.IsValid)
{
Post post = GetPost(id);
post.Title = title;
post.Body = body;
post.Date = date;
post.Tags.Clear();
tags = tags ?? string.Empty;
string[] tagNames = tags.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
foreach (string tagName in tagNames)
{
post.Tags.Add(GetTag(tagName));
}
if (!id.HasValue || id == 0)
{
_db.Posts.Add(post);
}
_db.SaveChanges();
return RedirectToAction("Details", new { id = post.Id });
}
return View();
}
public ActionResult Edit(int? id)
{
Post post = GetPost(id);
var tagList = new StringBuilder();
foreach (Tag tag in post.Tags)
{
tagList.AppendFormat("{0}", tag.Name);
}
ViewBag.Tags = tagList.ToString();
return View(post);
}
public Tag GetTag(string tagName)
{
//return model.Tags.FirstOrDefault(x => x.Name == tagName) ?? new Tag() { Name = tagName };
return new Tag() { Name = tagName };
}
private Post GetPost(int? id)
{
if (id.HasValue && id != 0)
{
return model.Posts.FirstOrDefault(x => x.Id == id);
}
return new Post();
}
When I had the following snippit of code it kept throwing a object instance exception when I try to SaveChanges.
if (!id.HasValue || id == 0)
{
model.Posts.Add(post);
}
model.SaveChanges();
So I had to end up throwing a local instance of the model and use it that way.
var _db = new BlogDb();
And further down
if (!id.HasValue || id == 0)
{
_db.Posts.Add(post);
}
_db.SaveChanges();
Am I just misunderstanding how to work with the database context?
Also what is the purpose of making a constructor pass in the model?

private readonly BlogDb model;
public PostsController(BlogDb model)
{
this.model = model;
}
public PostsController()
{
}
You have 2 constructors - only one of them sets the model field. The default controller factory will only ever call the default, parameterless constructor, leaving the parameterized one unused (and thus, the model field remains null).
That's why you get a NullReferenceException when you access model: the field's reference was never assigned!
This:
var _db = new BlogDb();
Is a sloppy fix. Instead, chain your constructors:
public PostsController()
: this(new BlogDb())
{
}
public PostsController(BlogDb model)
{
this.model = model;
}
This way the model field will be assigned regardless of which constructor is used to create the controller.
Note that this is called bastard injection, a dependency-injection anti-pattern. Either you DI, or you don't - in other words, if you're going to be using the default controller factory, do this instead:
public PostsController()
{
this.model = new BlogDb();
}
or even:
private readonly BlogDb model = new BlogDb();
And then you can remove all constructors... and you have a tightly coupled piece of code.
One good (excellent) read on the subject, is Dependency Injection in .NET, by Mark Seemann.
IDisposable
Your BlogDb inheriting EF's DbContext, it implements the IDisposable interface, which means you need to think of how you're going to call Dispose() on that instance.
By making it an instance-level private field [and not doing proper dependency injection], you've made your life very complicated.
You want an instance per request - because you'll want that resource to be in-scope only as long as it needs to be, and that means a new instance for each ActionResult method; something like this:
IEnumerable<Post> posts;
using (var context = new BlogDb())
{
posts = context.Posts.ToList();
return View(posts);
}
The using block ensures IDisposable.Dispose() will get called on context. The only other option, is to call context.Dispose() manually; if context is some private readonly BlockDb _context; field instead, things will only go well until the disposed context is used again.
As a general rule of thumb, the object that is responsible for creating an IDisposable instance, is also responsible for disposing it.
Constructor Injection
Now if you implement your own IControllerFactory use an IoC container, and wire it up in global.asax, it's a different story.
Now the object that's responsible for instantiating the disposable context is also responsible for disposing it, and can do so once per request, i.e. to inject a new instance, through the constructor, at each request - and then dispose it.
That's when you have an instance-level private readonly BlogDb _context; constructor-injected by the IoC container - because you know that whoever is giving you that instance, will be disposing it properly (because you've set it up that way).
You won't need the default constructor anymore, so keep things simple with a single constructor that ends up statically documenting every dependency the class has, through the constructor signature:
private readonly BlogDb _context;
public PostsController(BlogDb context)
{
_context = context;
}
The foundation of dependency injection, is to depend on abstractions, not implementations. By doing that...
private readonly IPostsService _service;
public PostsController(IPostsService service)
{
_service = service;
}
You're now free to inject a BlogDb (given BlogDb : IBlogService)... or anything else that implements that interface, perhaps a mock implementation, that make it possible to write unit tests that can cover all controller actions, without hitting the database.
By depending directly on BlogDb, the controller is tied to the specific implementation details of that class; it's tightly coupled. By depending on an abstraction, loose coupling is achievable.

The model field will be null because you haven't told MVC how it should handle controllers with non-default constructors. MVC uses something called a controller factory, that by default will pick a parameterless constructor, if it exists, when creating your controllers. If you remove the parameterless contructor, you will probably get an exception.
If you want to be able to "inject" parameters into your controllers, you need to do one of these:
Implement the IControllerFactory interface and set it using the ControllerBuilder.Current.SetControllerFactory method.
implement the IDependencyResolver interface and set it using the DependencyResolver.SetResolver method.
Implementing these interfaces is usually done using an IoC container. There's existing implementations for the most popular ones out there, that you can just plug in and go. I suggest your read more about MVC and Dependency Injection.

Related

Applying Dependency Injection when base-class constructor contains arguments

I have a base API controller that I want all controllers to execute on request, to act as a security mechanism. Here is that controller
public abstract class SharepointAuthController : ApiController
{
private ClientContext clientContext;
public SharepointAuthController()
: base()
{
ValidateContext();
}
protected void ValidateContext()
{
if (ControllerContext.Request != null)
{
var spContext = SharePointApiControllerContextProvider.Current.GetSharePointContext(ControllerContext);
clientContext = spContext.CreateUserClientContextForSPHost();
if (clientContext == null)
{
throw new AuthenticationException();
}
}
}
protected string GetUserName()
{
User spUser = null;
var spContext = SharePointApiControllerContextProvider.Current.GetSharePointContext(ControllerContext);
using (clientContext = spContext.CreateUserClientContextForSPHost())
{
if (clientContext != null)
{
spUser = clientContext.Web.CurrentUser;
clientContext.Load(spUser, user => user);
clientContext.ExecuteQuery();
return spUser.Email;
}
}
throw new AuthenticationException();
}
}
And a controller that calls it
public class CallPointsController : SharepointAuthController
{
private readonly ICallPointRepository _callPointRepository;
public CallPointsController(ICallPointRepository callPointRepository)
{
_callPointRepository = callPointRepository;
}
[SharePointContextFilter]
[HttpGet]
[Route("api/callpoints")]
public List<CallPointDto> Get()
{
string user = base.GetUserName();
if (!string.IsNullOrEmpty(user))
{
return _callPointRepository.ListAll();
}
return null;
}
}
I now want to extend the SharepointAuthController to get additional information about the user (exists in DB). I want to be able to pass repository into the base class's constructor for proper DI, something like so
private ClientContext clientContext;
private _repo Repo;
public SharepointAuthController(Repo repo)
: base()
{
ValidateContext();
_repo = repo;
}
protected UserDto GetUserName()
{
User spUser = null;
var spContext = SharePointApiControllerContextProvider.Current.GetSharePointContext(ControllerContext);
using (clientContext = spContext.CreateUserClientContextForSPHost())
{
if (clientContext != null)
{
spUser = clientContext.Web.CurrentUser;
clientContext.Load(spUser, user => user);
clientContext.ExecuteQuery();
return _repo.GetAdditionalUserInfo(spUser.Email);
}
}
throw new AuthenticationException();
}
However just doing this does not work, because the class that calls into this baseclass is not setup correctly
There is no argument given that corresponds to the
required formal parameter 'repo' of Repo
Am I going about this the right way? I could just call into Repo class from the Auth controller without DI
To answer your question:
You need to inject the parameter into your inherited class and pass it on to the parent:
public class SharepointAuthController
{
public SharepointAuthController(Repo repo)
{
ValidateContext();
_repo = repo;
}
// rest of controller ...
}
public class CallPointsController : SharepointAuthController
{
private readonly ICallPointRepository _callPointRepository;
public CallPointsController(ICallPointRepository callPointRepository, Repo repo)
: base(repo)
{
_callPointRepository = callPointRepository;
}
}
On a different note: To do authentication, it's best not to use a base controller. Rather create an attribute (eg: SharepointAuthAttribute) that inherits from AuthorizeAttribute and do the authentication in there.
Then, you can apply that attribute to the controllers that need it.
The use of base classes is discouraged in general. The common saying is:
Composition over inheritance
Base classes are typically a bad idea, because:
They result in an extra dependency on a concrete class and with that introduces strong coupling, while DI promotes loose coupling.
This strong coupling makes your concrete controllers much harder to test, which is exaggerates in your case because you force business logic to be called inside your constructor, while injection constructors should be simple.
When base classes are used for cross-cutting concerns (as is in your case), they start to become a magnet for more and more cross-cutting concerns. This causes the base class to become this ever changing class that violates both the Single Responsibility Principle and Open/Closed Principle.
These base classes tend to require dependencies of their own. This is problematic because it easily pulls you into the Temporal Coupling code smell or the Service Locator anti-pattern. When you apply dependencies through the base class's constructor, the constructors of your derived classes require those dependencies as well. This means that every time you change or add a dependency to the base class, it causes sweeping changes throughout the application, because every derived class needs to be changed as well. To mitigate this, your options are to revert to property injection (which causes Temporal Coupling) or revert to the Service Locator anti-pattern. Both styles have serious downsides.
So instead of using base classes, composition is a much better way of designing your system and especially a much better way to apply cross-cutting concerns such as security.
A typical way of applying cross-cutting concerns is by the use of decorators. Web API however makes it impossible to wrap controller types with decorators. With Web API, the designed pattern for applying cross-cutting concerns on the controller level is the use of DelegatingHandlers.
You've added a parameter to the base class' constructor:
public SharepointAuthController(Repo repo)
: base()
{
//...
}
But you don't supply that parameter in the derived class' constructor:
public CallPointsController(ICallPointRepository callPointRepository)
{
//...
}
It needs to be supplied:
public CallPointsController(ICallPointRepository callPointRepository, Repo repo)
: base(repo)
{
//...
}
Otherwise the derived class would have no way of constructing the base class, and therefore can't be an instance of the base class.

Moving logic from controller action to a "service layer" without using IoC/DI, UoW and repository patterns in ASP.NET MVC

Recently i've working on an ASP.NET MVC5 project, i dived right in and wrote all my logic right in the action method and after doing this for a few controllers i've noticed that i have been duplicating certain business rules and could do with being lifted out and shared between controllers.
From what i've read, the m in asp.net mvc is a layer consisting of entities, viewmodels and services, the latter holding all your shared business logic
now i'm trying to keep things as simple as possible, i don't want to wrap entity framework in some UoW/Repo and use it as-is, it is very unlikely that i'll stop using entity framework in this applications lifetime and i'm not doing unit tests and i'm not that bothered about tight coupling, so i don't feel i need an IoC container, but all the tutorials i've read seems to use either an IoC container or wraps dbcontext/ef in a UoW/Repo.
I've read that there should only be a single instance (which in the tutorials i've seen is managed via an IoC container) of DbContext per httprequest, would this be achieved by instantiating it in the controllers constructor and then passing that reference to any services needed in the controller and then disposing it at the end of the request? is this the correct way of managing dbcontext?
Controller example:
public class SupplierController : Controller
{
private Meerkat3Context context;
private SupplierService supplierService;
private ratingService SupplierRatingService;
public SupplierController()
{
// instantiate the dbcontext
this.context = new Meerkat3Context();
// pass dbcontext into the constructors of my services
this.supplierService = New SupplierService(context);
this.ratingService = New SupplierRatingService(context);
}
public ActionResult Index(Guid id)
{
var supplier = supplierService.getSupplier(id);
// construct viewmodel
return new SupplierIndexViewModel()
{
SupplierId = supplier.Id,
SupplierName = supplier.Name,
SupplierRating = ratingService.getHighestRating(supplier.Id),
NearbySuppliers = supplierService.getNearbySuppliers(supplier.Id),
// etc
};
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
context.Dispose();
}
base.Dispose(disposing);
}
}
Service examples:
public class SupplierService
{
private Meerkat3Context context;
public SupplierService(Meerkat3Context context)
{
this.context = context;
}
public Supplier getSupplier(Guid id)
{
return context.Where(x => x.SupplierId == id)
.FirstOrDefault()
.Select(x => new Supplier()
{
Id = x.Id,
Name = x.Name
// etc
});
}
public Supplier getNearbySuppliers(Guid id)
{
return context.Suppliers.Where(x => context.SupplierAddresses
.Where(y => y.AddressTypeId == AddressTypes.Location)
.Select(z => z.Address.TownCity)
.Contains(x.SupplierAddresses
.Where(y => y.AddressTypeId == AddressTypes.Location)
.FirstOrDefault()
.Address.TownCity)
);
}
}
public class SupplierRatingService
{
private Meerkat3Context context;
public RatingService(Meerkat3Context context)
{
this.context = context;
}
public SupplierRating getHighestRating(Guid id)
{
return context.SupplierRating
.Where(x => x.SupplierId == id)
.OrderBy(x => x.RatingValue)
.FirstOrDefault()
}
}
If you're trying to strip out the repeated code, this should be fairly simple. In VS you can highlight a section of code and use the hotkeys Ctrl+R,Ctrl+M for refactor, or you can do so by using the context menu highlight code section > right-click > Refactor > Extract Method.
If the usage of the repeated code can be replicated for all entities, you can create a static class that houses this common functionality.
public sealed class Utlities
{
public static CommonA() { }
public static CommonB() { }
... etc...
}
And you can call them easily using Utilities.CommonA(). Another way to reduce redundancy is to use ViewModels. Basically create a copy of the entity you want to use as a ViewModel with additional properties required for the View. If the models have data in common, create a base class to inherit those commonalities from.
public class BaseViewModel
{
public Type Prop {get; set;}
public Type Prop2 {get; set;}
...etc...
}
public class SpecificViewModel : BaseViewModel
{
SpecificViewModel(Type Prop, Type Prop2) : base(Prop, Prop2, ...etc...) { }
public Type specificProp {get; set;}
...etc...
}
If I understood your question correctly that is.
If what you want is simply moving out reusable logic then your approach is good enough. But please bear in mind that:
it isn't testable (you can't isolate your dependencies and
You're still duplicating the logic, even if it's simply an object construction logic (e.g., in every controller where you need SupplierService you'll have to instantiate Meerkat3Context as well). That can get quite tedious (and that's where DI comes in handy)
With an IoC container your controller would look like.
public class SupplierController : Controller
{
//the controller doesn't need to create the db context now
//this concern is handled now by the IoC container
private SupplierService supplierService;
private RatingService SupplierRatingService;
public SupplierController(SupplierService supplierService, RatingService ratingService)
{
// we don't have to pass the db context now to services, since we retrieve the services from the IoC container. The IoC container auto-wires the services
this.supplierService = supplierService;
this.ratingService = ratingService;
}
public ActionResult Index(Guid id)
{
var supplier = supplierService.getSupplier(id);
// construct viewmodel
return new SupplierIndexViewModel()
{
SupplierId = supplier.Id,
SupplierName = supplier.Name,
SupplierRating = ratingService.getHighestRating(supplier.Id),
NearbySuppliers = supplierService.getNearbySuppliers(supplier.Id),
// etc
};
}
// the controller doesn't need a dispose method since the IoC container will dispose the dbcontext for us
}
You don't have to follow the Dependency Inversion Principle to use an IoC container, but you can count on a IoC container to create and to manage the lifetime of your services objects.
You configure the IoC container to create a single instance of a dbcontext per a web request. The good part is this is configurable and, if you later decide is better to have a different dbcontext instance per service, then you just change this in a single place and not in every controller and every action method where you use the new keyword.

Dependency Injection in Model classes (entities)

I am building an ASP.NET Core MVC application with Entity Framework Code-First.
I implemented a simple repository pattern, providing basic CRUD operations for all the model classes I have created.
I chose to follow all the recommendations provided in docs and DI is one of these.
In ~~.NET 5~~ (6 years later update: .net 5 was the alpha name of .net core 1.0) dependency injection works very well for any class that we do not directly instantiate (e.g.: controllers, data repositories, ...).
We simply inject them via the constructor, and register the mappings in the Startup class of the application :
// Some repository class
public class MyRepository : IMyRepository
{
private readonly IMyDependency _myDependency;
public MyRepository(IMyDependency myDependency)
{
_myDependency = myDependency;
}
}
// In startup.cs :
services.AddScoped<IMyDependency, MyDependency>();
services.AddScoped<IMyRepository, MyRepository>();
The problem is that in some of my model classes, I would like to inject some of the dependencies I have declared.
But I think that I cannot use the constructor injection pattern because model classes are often explicitly instantiated. Therefore, I would need to provide myself with the dependencies, which I can't.
So my question is: is there another way than constructor injection to inject dependencies, and how? I was for example thinking of an attribute pattern or something like that.
As I already explained in a comment, when creating an object using new, there is nothing from the dependency injection framework that is involved in the process. As such, it’s impossible for the DI framework to magically inject things into that object, it simply doesn’t know about it.
Since it does not make any sense to let the DI framework create your model instances (models are not a dependency), you will have to pass in your dependencies explicitly if you want the model to have them. How you do that depends a bit on what your models are used for, and what those dependencies are.
The simple and clear case would be to just have your model expect the dependencies on the constructor. That way, it is a compile time error if you do not provide them, and the model has access to them right away. As such, whatever is above, creating the models, is required to have the dependencies the model type needs. But at that level, it’s likely that this is a service or a controller which has access to DI and can request the dependency itself.
Of course, depending on the number of dependencies, this might become a bit complicated as you need to pass them all to the constructor. So one alternative would be to have some “model factory” that takes care of creating the model object. Another alternative would also be to use the service locator pattern, passing the IServiceCollection to the model which can then request whatever dependencies it needs. Note that is generally a bad practice and not really inversion of control anymore.
Both these ideas have the issue that they modify the way the object is created. And some models, especially those handled by Entity Framework, need an empty constructor in order for EF to be able to create the object. So at that point you will probably end up with some cases where the dependencies of your model are not resolved (and you have no easy way of telling).
A generally better way, which is also a lot more explicit, would be to pass in the dependency where you need it, e.g. if you have some method on the model that calculates some stuff but requires some configuration, let the method require that configuration. This also makes the methods easier to test.
Another solution would be to move the logic out of the model. For example the ASP.NET Identity models are really dumb. They don’t do anything. All the logic is done in the UserStore which is a service and as such can have service dependencies.
The pattern often used in domain driven design (rich domain model to be specific) is to pass the required services into the method you are calling.
For example if you want to calculate the vat, you'd pass the vat service into the CalculateVat method.
In your model
public void CalculateVat(IVatCalculator vatCalc)
{
if(vatCalc == null)
throw new ArgumentNullException(nameof(vatCalc));
decimal vatAmount = vatcalc.Calculate(this.TotalNetPrice, this.Country);
this.VatAmount = new Currency(vatAmount, this.CurrencySymbol);
}
Your service class
// where vatCalculator is an implementation IVatCalculator
order.CalculateVat(vatCalculator);
Finally your service can inject another services, like a repository which will fetch the tax rate for a certain country
public class VatCalculator : IVatCalculator
{
private readonly IVatRepository vatRepository;
public VatCalculator(IVatRepository vatRepository)
{
if(vatRepository == null)
throw new ArgumentNullException(nameof(vatRepository));
this.vatRepository = vatRepository;
}
public decimal Calculate(decimal value, Country country)
{
decimal vatRate = vatRepository.GetVatRateForCountry(country);
return vatAmount = value * vatRate;
}
}
I know my answer is late and may not exactly what you're asking for, but I wanted to share how I do it.
First of all: If you want to have a static class that resolves your dependencies this is a ServiceLocator and it's Antipattern so try not to use it as you can.
In my case I needed it to call MediatR inside of my DomainModel to implement the DomainEvents logic.
Anyway, I had to find a way to call a static class in my DomainModel to get an instance of some registered service from DI.
So I've decided to use the HttpContext to access the IServiceProvider but I needed to access it from a static method without mention it in my domain model.
Let's do it:
1- I've created an interface to wrap the IServiceProvider
public interface IServiceProviderProxy
{
T GetService<T>();
IEnumerable<T> GetServices<T>();
object GetService(Type type);
IEnumerable<object> GetServices(Type type);
}
2- Then I've created a static class to be my ServiceLocator access point
public static class ServiceLocator
{
private static IServiceProviderProxy diProxy;
public static IServiceProviderProxy ServiceProvider => diProxy ?? throw new Exception("You should Initialize the ServiceProvider before using it.");
public static void Initialize(IServiceProviderProxy proxy)
{
diProxy = proxy;
}
}
3- I've created an implementation for the IServiceProviderProxy which use internally the IHttpContextAccessor
public class HttpContextServiceProviderProxy : IServiceProviderProxy
{
private readonly IHttpContextAccessor contextAccessor;
public HttpContextServiceProviderProxy(IHttpContextAccessor contextAccessor)
{
this.contextAccessor = contextAccessor;
}
public T GetService<T>()
{
return contextAccessor.HttpContext.RequestServices.GetService<T>();
}
public IEnumerable<T> GetServices<T>()
{
return contextAccessor.HttpContext.RequestServices.GetServices<T>();
}
public object GetService(Type type)
{
return contextAccessor.HttpContext.RequestServices.GetService(type);
}
public IEnumerable<object> GetServices(Type type)
{
return contextAccessor.HttpContext.RequestServices.GetServices(type);
}
}
4- I should register the IServiceProviderProxy in the DI like this
public void ConfigureServices(IServiceCollection services)
{
services.AddHttpContextAccessor();
services.AddSingleton<IServiceProviderProxy, HttpContextServiceProviderProxy>();
.......
}
5- Final step is to initialize the ServiceLocator with an instance of IServiceProviderProxy at the Application startup
public void Configure(IApplicationBuilder app, IHostingEnvironment env,IServiceProvider sp)
{
ServiceLocator.Initialize(sp.GetService<IServiceProviderProxy>());
}
As a result now you can call the ServiceLocator in your DomainModel classes "Or and needed place" and resolve the dependencies that you need.
public class FakeModel
{
public FakeModel(Guid id, string value)
{
Id = id;
Value = value;
}
public Guid Id { get; }
public string Value { get; private set; }
public async Task UpdateAsync(string value)
{
Value = value;
var mediator = ServiceLocator.ServiceProvider.GetService<IMediator>();
await mediator.Send(new FakeModelUpdated(this));
}
}
The built-in model binders complain that they cannot find a default ctor. Therefore you need a custom one.
You may find a solution to a similar problem here, which inspects the registered services in order to create the model.
It is important to note that the snippets below provide slightly different functionality which, hopefully, satisfies your particular needs. The code below expects models with ctor injections. Of course, these models have the usual properties you might have defined. These properties are filled in exactly as expected, so the bonus is the correct behavior when binding models with ctor injections.
public class DiModelBinder : ComplexTypeModelBinder
{
public DiModelBinder(IDictionary<ModelMetadata, IModelBinder> propertyBinders) : base(propertyBinders)
{
}
/// <summary>
/// Creates the model with one (or more) injected service(s).
/// </summary>
/// <param name="bindingContext"></param>
/// <returns></returns>
protected override object CreateModel(ModelBindingContext bindingContext)
{
var services = bindingContext.HttpContext.RequestServices;
var modelType = bindingContext.ModelType;
var ctors = modelType.GetConstructors();
foreach (var ctor in ctors)
{
var paramTypes = ctor.GetParameters().Select(p => p.ParameterType).ToList();
var parameters = paramTypes.Select(p => services.GetService(p)).ToArray();
if (parameters.All(p => p != null))
{
var model = ctor.Invoke(parameters);
return model;
}
}
return null;
}
}
This binder will be provided by:
public class DiModelBinderProvider : IModelBinderProvider
{
public IModelBinder GetBinder(ModelBinderProviderContext context)
{
if (context == null) { throw new ArgumentNullException(nameof(context)); }
if (context.Metadata.IsComplexType && !context.Metadata.IsCollectionType)
{
var propertyBinders = context.Metadata.Properties.ToDictionary(property => property, context.CreateBinder);
return new DiModelBinder(propertyBinders);
}
return null;
}
}
Here's how the binder would be registered:
services.AddMvc().AddMvcOptions(options =>
{
// replace ComplexTypeModelBinderProvider with its descendent - IoCModelBinderProvider
var provider = options.ModelBinderProviders.FirstOrDefault(x => x.GetType() == typeof(ComplexTypeModelBinderProvider));
var binderIndex = options.ModelBinderProviders.IndexOf(provider);
options.ModelBinderProviders.Remove(provider);
options.ModelBinderProviders.Insert(binderIndex, new DiModelBinderProvider());
});
I'm not quite sure if the new binder must be registered exactly at the same index, you can experiment with this.
And, at the end, this is how you can use it:
public class MyModel
{
private readonly IMyRepository repo;
public MyModel(IMyRepository repo)
{
this.repo = repo;
}
... do whatever you want with your repo
public string AProperty { get; set; }
... other properties here
}
Model class is created by the binder which supplies the (already registered) service, and the rest of the model binders provide the property values from their usual sources.
HTH
Is there another way than constructor injection to inject dependencies, and how?
The answer is "no", this cannot be done with "dependency injection". But, "yes" you can use the "service locator pattern" to achieve your end-goal.
You can use the code below to resolve a dependency without the use of constructor injection or the FromServices attribute. Additionally you can new up an instance of the class as you see fit and it will still work -- assuming that you have added the dependency in the Startup.cs.
public class MyRepository : IMyRepository
{
public IMyDependency { get; } =
CallContextServiceLocator.Locator
.ServiceProvider
.GetRequiredService<IMyDependency>();
}
The CallContextServiceLocator.Locator.ServiceProvider is the global service provider, where everything lives. It is not really advised to use this. But if you have no other choice you can. It would be recommended to instead use DI all the way and never manually instantiate an object, i.e.; avoid new.
I'm simply adding some supplemental information here to the answers provided that can help.
IServiceProvider was provided in the accepted answer, but not the important IServiceProvider.CreateScope() method. You can use it to create scopes as necessary that you added through ConfigureServices.
I'm not sure if IServiceProvider is actually a Service Locator pattern behind the scenes or not, but it's how you create scopes as far as I know. At least in the case if it is a Service Locator pattern, it's the official one for today in .NET, and so it's not compounded by the problems of writing your own Service Locator, which I also agree is anti-pattern.
Example, Startup.cs/ConfigureServices and Configure:
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<SomeDbContext>(options =>
{
options.UseSqlServer(Configuration.GetSection("Databases").GetSection("SomeDb")["ConnectionString"]);
options.UseQueryTrackingBehavior(QueryTrackingBehavior.NoTracking);
}, ServiceLifetime.Scoped);
services.AddMvcCore().AddNewtonsoftJson();
services.AddControllersWithViews();
}
public async void Configure(IApplicationBuilder app, IWebHostEnvironment env, IServiceProvider provider)
{
...
IServiceScope scope = provider.CreateScope();
SomeDbContext context = scope.ServiceProvider.GetRequiredService<SomeDbContext>();
SomeModelProxyClass example = new SomeModelProxyClass(context);
await example.BuildDefaults(
Configuration.GetSection("ProfileDefaults").GetSection("Something"),
Configuration.GetSection("ProfileDefaults").GetSection("SomethingSomething"));
scope.Dispose();
}
The above is for doing some default interactions on Startup, maybe if you need to build some default records in your database on a first usage, just as an example.
Ok so let's get to your repository and dependency though, will they work?
Yep!
Here's a test in my own CRUD project, I made a simple minimalist implementation of your IMyDependency and IMyRepository like so, then added them scoped as you did to Startup/ConfigureServices:
public interface IMyRepository
{
string WriteMessage(string input);
}
public interface IMyDependency
{
string GetTimeStamp();
}
public class MyDependency : IMyDependency
{
public MyDependency()
{
}
public string GetTimeStamp()
{
return DateTime.Now.ToLongDateString() + " " + DateTime.Now.ToLongTimeString();
}
}
public class MyRepository : IMyRepository
{
private readonly IMyDependency _myDependency;
public MyRepository(IMyDependency myDependency)
{
_myDependency = myDependency;
}
public string WriteMessage(string input)
{
return input + " - " + _myDependency.GetTimeStamp();
}
}
Here ContextCRUD is a Model class from my own project not derived from Scaffold-DbContext tooling like my other database classes, it's a container of logic from those scaffold Model classes, and so I put it in the namespace Models.ProxyModels to hold its own business logic for doing CRUD operations so that the Controllers are not gummed up with logic that should be in the Model:
public ContextCRUD(DbContext context, IServiceProvider provider)
{
Context = context;
Provider = provider;
var scope = provider.CreateScope();
var dep1 = scope.ServiceProvider.GetService<IMyRepository>();
string msg = dep1.WriteMessage("Current Time:");
scope.Dispose();
}
Debugging I get back the expected results in msg, so it all checks out.
The calling code from the Controller for reference, just so you can see how IServiceProvider is passed from upstream by constructor injection in the Controller:
[Route("api/[controller]")]
public class GenericController<T> : Controller where T: DbContext
{
T Context { get; set; }
ContextCRUD CRUD { get; set; }
IConfiguration Configuration { get; set; }
public GenericController(T context, IConfiguration configuration, IServiceProvider provider)
{
Context = context;
CRUD = new ContextCRUD(context, provider);
Configuration = configuration;
}
...
You can do it, check out [InjectionMethod] and container.BuildUp(instance);
Example:
Typical DI constructor (NOT NEEDED IF YOU USE InjectionMethod) public
ClassConstructor(DeviceHead pDeviceHead) {
this.DeviceHead = pDeviceHead; }
This attribute causes this method to be called to setup DI.
[InjectionMethod] public void Initialize(DeviceHead pDeviceHead) {
this.DeviceHead = pDeviceHead; }

Centralizing CloudStorageAccount and TableServiceContext instances

In an ASP.NET MVC 3 Web Role, I have realized that I have been writing the below code a lot:
var account =
CloudStorageAccount.Parse(
RoleEnvironment.GetConfigurationSettingValue("DataConnectionString")
);
var ctx =
account.CreateCloudTableClient().GetDataServiceContext();
So, I decided to Centralize this for the entire ASP.NET MVC application and I created the below class with static properties:
internal class WindowsAzureStorageContext {
public static CloudStorageAccount StorageAccount {
get {
return
CloudStorageAccount.Parse(
RoleEnvironment.GetConfigurationSettingValue("DataConnectionString")
);
}
}
public static TableServiceContext TableServiceCtx {
get {
return
StorageAccount.CreateCloudTableClient().GetDataServiceContext();
}
}
}
And, I am using this as below inside my controllers:
public class HomeController : Controller {
private readonly TableServiceContext ctx =
WindowsAzureStorageContext.TableServiceCtx;
public ViewResult Index() {
var model = ctx.CreateQuery<TaskEntity>(Constants.TASKS_TABLE).
Where(x => x.PartitionKey == string.Empty);
return View(model);
}
public ViewResult Create() {
return View();
}
[ActionName("Create")]
[HttpPost, ValidateAntiForgeryToken]
public ViewResult Create_post(TaskEntity taskEntity) {
ctx.AddObject(Constants.TASKS_TABLE, new TaskEntity(taskEntity.Task));
ctx.SaveChangesWithRetries();
return RedirectToAction("Index");
}
}
I know that this is not a unit test friendly and I should reach out that TableServiceContext instance through a interface by DI but when I do that, I consider using this WindowsAzureStorageContext class as well to get an instance of TableServiceContext class.
Is this a good practice? Would it hurt me in any point because I am using the same class for the entire application life-cycle?
Is there any know pattern to do this?
I don't see any problem with doing that. Looks like a nice clean way to do it. I don't know of a known pattern to do this but was just thinking there should be yesterday.
I think you can use repository pattern for a generic data context, with a generic interface on top of it. Not sure if it helps but you can refer my blog http://blogs.shaunxu.me/archive/2010/03/15/azure-ndash-part-5-ndash-repository-pattern-for-table-service.aspx
I don't believe that there is any shared state between instances of the context. With that said, the transaction time for the controller to execute is non-trivial. The longer you hold onto the context, the more likely you are to get conflicts. I've found that one way to keep conflicts and overlaps to a minimum is to keep the load/change/save cycle as short as possible.
Erick

Should Factories Persist Entities?

Should factories persist entities they build? Or is that the job of the caller? Pseudo Example Incoming:
public class OrderFactory
{
public Order Build()
{
var order = new Order();
....
return order;
}
}
public class OrderController : Controller
{
public OrderController(IRepository repository)
{
this.repository = repository;
}
public ActionResult MyAction()
{
var order = factory.Build();
repository.Insert(order);
...
}
}
or
public class OrderFactory
{
public OrderFactory(IRepository repository)
{
this.repository = repository;
}
public Order Build()
{
var order = new Order();
...
repository.Insert(order);
return order;
}
}
public class OrderController : Controller
{
public ActionResult MyAction()
{
var order = factory.Build();
...
}
}
Is there a recommended practice here?
As a general rule the factory has only one responsibility: create an instance and return it. I would not mix in persistence. I would view it as the responsibility of another class. In this case, it would be the controller.
The Factory's main purpose is the creation of objects. Once that object has been created it's up to you to decide what you want to do with it.
The only case where this would be different is if there's also a requirement that only once instance of the created object should exist, in which case you'll have some kind of pseudo-factory-singleton hybrid pattern going on.
If you decide to use a factory for singleton objects, you will need to manage the persistence of the singleton object. Other than that, I can't see why you'd want to have factories manage persistence.
Actually, having factories manage persistence - with the exception of when singletons are involved - would lead to the very opposite of proper separation of concerns, which is the raison d'etre for using factories in the first place.

Categories