How to inject dependencies using Ninject In ASP.NET WebForm? - asp.net

I have a fair idea of using the Repository Pattern and have been attempting to "upgrade" our current way of creating ASP .Net websites. So i do the following
Create a solution with a class project called DataAccessLayer and another class project called BusinessLogicLayer. Finally a 3rd project which is my ASP .Net website (a normal site).
I add a dbml file to the DAL and drag a table, then in my BLL i add an interface and a class which implements this interface:
My interface
namespace BLL.Interfaces
{
interface IUser
{
List<User> GetAllUsers();
}
}
In my class
namespace BLL.Services
{
public class UserService : BLL.Interfaces.IUser
{
public List<User> GetUsers()
{
throw new NotImplementedException();
}
}
}
I know the code is not fully completed, but there for illustrative purposes.
So i right click the BLL project > Manage NuGet Packages > Searched for Ninject and found a few. I was overwhelmed with the number of entries returned after after further research i am lost in how to add Ninject to a normal ASP .Net website? Specifically which addin i require? As there are many MVC and reading further i think im a little confused.
I was trying to add it to the BLL project as thats where i THINK it should go so i can register my services in there.
Could anyone guide me in what i need to so in order to use Ninject entries but im not using MVC?

Install Ninject.Web either from "Package Manager Console" or NuGet.
Version is 3.2.1 as of this writing.
OR
It will install the following 4 packages -
Sample Service Class
public interface IUserService
{
List<string> GetUsers();
}
public class UserService : IUserService
{
public List<string> GetUsers()
{
return new List<string> {"john", "eric"};
}
}
Then add binding to ~/App_Start/NinjectWebCommon.cs.
In code behind page, property inject using [Inject] attribute.

In Addition in answer by win I would advise people not to get confused by using Constructor based injection in ASP.NET Webforms as Web Forms doesn't support constructor based injection simply. In default configuration they only support Property based Injections as already demonstrated by Win.

Related

Xamarin Forms: Open downloaded file in default Android/iOS application

I am using Xamarin Forms. I would like to download jpg file (it is done) and then open that jpg in default application on Android/iOS (opening photo browser with this photo). Of course photo is single example, I would like to open any file in default application.
I found several solutions native-only but my application is designed to be cross-platform. I though that I can use Launcher from Xamarin.Essentials package but apparently I can't.
How to achieve this?
You can have a try with Xamarin.Essentials: Launcher:
var fn = "File.txt";
var file = Path.Combine(FileSystem.CacheDirectory, fn);
File.WriteAllText(file, "Hello World");
await Launcher.OpenAsync(new OpenFileRequest
{
File = new ReadOnlyFile(file)
});
I found several solutions native-only
Opening something in another app is quite close to the system for a mobile application and there are some things to consider, which dependend on the platform. Usually, mobile apps run in a sandbox with very limited access to the surrounding system. Particularly this means that, if you downloaded a file to the sandbox of your app, other apps (which native viewers are), aren't allowed to access the file.
On Android, you can copy the file to a shared space (see Application.Context.GetExternalFilesDir(null)) and then open it. This might be possible with Essentials, but I'm not quite sure, but since we're on the Android platform anyway now, you could create an intent now anyway.
On iOS you create controllers from within your app (for example the QLPreviewController to preview the file) that may access items in your sandbox. Depending on the type of controller (e.g. UIActivityViewController) they may open other apps.
How to use this platform-independently?
Since you are programming a platform independent app, you'll have to take care that the correct class is called to the platform dependent work. There are several options how you can achieve this
Use the DependencyService
Use a real dependency injection framework
Use an abstract base class with initialization in the platform dependent projects
DependencyService
To use the Xamarin.Forms DependencyService you need two things
An interface for the functionality you'd like to implement
One implementation per platform
Assuming you hvae a simple interface to share a file
public IShareFile
{
void ShareFile(string fileName);
}
you can implement an implementation of this interface on each platform and add the DependencyAttribute to the assembly. e.g. for iOS:
[assembly: Dependency(typeof(MyApp.iOS.DeviceOrientationService))]
namespace MyApp.iOS
{
public class ShareFile : IShareFile
{
public void Share(string fileName)
{
// implementation goes here
}
}
}
The general scaffold is the same for Android, albeit the implementation differs.
Using a real dependency injection framework
Basically it's pretty much the same. You can skip the DependencyAttribute, though. In order to make the implementation available you'll have to get hold of the DI container from your platform specific code, which might be tricky. This might be an overshoot for a single dependency, but if you're using a DI container anyway and there are X dependencies, it might be worth the effort.
Using an abstract base class
Add an abstract base class to your project
public abstract class ShareFile
{
public static ShareFile Instance { get; protected set; }
public abstract void Share(string fileName);
}
and in your implementation in the platform specific project, you add an Init() method
internal class ShareFileImpl : ShareFile
{
public static void Init()
{
ShareFile.Instance = new ShareFileImpl();
}
public void Share(string fileName)
{
// implementation goes here
}
}
This init method must be called from your platform specific code. Most likely during initialization. The implementation can then be accessed via its abstraction from your platform independent code (of course you'll see only the abstraction, public methods added to ShareFileImpl won't be visible from your platform independent code).
ShareFile.Instance.Share(fileName);
A combination of the abstract class approach and dependency injection is also conceivable. When registering your classes in the DI framework, you could register the platform instance like
container.RegisterInstance<ShareFile>(ShareFile.Instance);
This way you can make use of the DI container features (e.g. constructor injection), while keeping the hassles of using the DI container from your platform specific project away from you. The drawback is, that you'll still have to call ShareFileImpl.Init() from your platform specfic code.

Why DbSet<> not works with asp.net core web application?

I'm working on an ASP.Net Core Web Application. While trying to set the dbset<>, I get this error.
This line of code gives error:
public DbSet<Person> Persons { get; set; }
Resharper suggests two options:
System.Data.Entity.
Microsoft.EntityFrameworkCore.
public System.Data.Entity.DbSet<Person> Persons { get; set; }
Can anyone please explain which one to chose: the first or second option?
I have included the necessary references.
using System.Data.Entity;
using System.Data.Entity.ModelConfiguration.Conventions;
using Microsoft.EntityFrameworkCore;
using DbContext = System.Data.Entity.DbContext;
I see this error:
The using directive is a shortcut to allow you to write just DbSet instead of System.Data.Entity.DbSet, for example.
But both System.Data.Entity and Microsoft.EntityFrameworkCore have a DbSet class, so it doesn't know which one to use, and it's not going to choose for you. So you have to tell it.
That said, you shouldn't be using both. Entity Framework 6 and Entity Framework Core are two completely different things. System.Data.Entity is for EF 6, and Microsoft.EntityFrameworkCore is for EF Core.
You probably shouldn't be using System.Data.Entity.
The reason is Ambigous Reference:
that DbSet<> is defined in both System.Data.Entity and Microsoft.EntityFrameworkCore.
Since you are working with ASPNET Core, recommended is to use Microsoft.EntityFrameworkCore

exception after upgrade ASP.NET Identity to 2.0

my project: VS2013, Entity Framework, Web forms, database first, Identity
I updated all NuGet packages of my project today (2014-4-15). Among them, Identity is upgraded to 2.0.0.0.
I thought things were going good, but unfortunately when I run the application, the following statement gives an exception.
namespace xxx.Models
{
// You can add User data for the user by adding more properties to your User class, please visit http://go.microsoft.com/fwlink/?LinkID=317594 to learn more.
public class ApplicationUser : IdentityUser
{
}
public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
public ApplicationDbContext()
: base("MyConnection")
{
}
}
...
}
The exception information is as follows. It asks me to do Code First Migration. But my project is a Database First webforms project. How can I solve this problem? Thanks!
An exception of type 'System.InvalidOperationException' occurred in Microsoft.AspNet.Identity.EntityFramework.dll but was not handled in user code
Additional information: The model backing the 'ApplicationDbContext' context has changed since the database was created.
This could have happened because the model used by ASP.NET Identity Framework has changed or the model being used in your application has changed.
To resolve this issue, you need to update your database. Consider using Code First Migrations to update the database (http://go.microsoft.com/fwlink/?LinkId=301867).
Before you update your database using Code First Migrations, please disable the schema consistency check for ASP.NET Identity by setting throwIfV1Schema = false in the constructor of your ApplicationDbContext in your application.
public ApplicationDbContext() : base("ApplicationServices", throwIfV1Schema:false)
You need to disable the schema consistency by doing what the error says. This is one time thing that happens when you upgrade from version 1.0 to 2.0.
public ApplicationDbContext() : base("MyConnection", throwIfV1Schema:false)
Next step - do the migrations.
Everything should work after that and you can remove this throwIfV1Schema:false
You can also take a look at this for more info
The problem is here :
public class ApplicationUser : IdentityUser
{
}
I think you should change to partial class to extend entity in Entity Framework. The reason is that EF will generate proxy class for each entity to connect to database.
The partial class should be write in the same namespace.

SPA Template VS2013 custom properties IdentityUser

I'm trying to add custom properties to the Identity User 2013 Spa Template. The Identity User model is not in the project when I F12 I get the model in the assembly which is not editable. I have read the tutorial to add a birth date to the Identity model however this example speaks about changing the Identity User model from a Web Forms prospective and it seems to have a UserIdentity model to edit. How do I add custom properties to the AspNetUser table?
I found the same. Most of the SPA template resources online seem to relate to the earlier (VS2012) version of the template which is quite confusing. However, by comparing the code generated by the MVC template I worked out what I needed to do which was.
In the Models folder create your own "ApplicationIdentity" and "ApplicationDbContext" classes. Include any additional properties that you want in your ApplicationIdentity class definition. In the example code below I have added a string for the email address.
using Microsoft.AspNet.Identity.EntityFramework;
namespace SimpleSPA.Models {
public class ApplicationUser: IdentityUser
{
public string Email { get; set; }
}
public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
public ApplicationDbContext():base("DefaultConnection")
{
}
}
}
Use the solution Search and Replace to replace all references to "IdentityUser" with your new ApplicationUser.
Update the Startup static constructor in Startup.Auth.cs so that the UserManagerFactory initialisation includes your new ApplicationDbContext as below.
UserManagerFactory = () => new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(new ApplicationDbContext()));
Rebuild the solution, check it builds OK.
Enable Entity Framework Code First migrations using the "Enable-Migrations" command in the Package Manager (PM) Console.
Add the initial migration using the PM command "Add-Migration Initial".
Initialise the database using the PM command "Update-Database".
Following this if you connect to the generated database you should see that the AspNetUsers table includes columns for your additional ApplicationUser properties. I haven't gone much further yet but I would expect that I will be able to access my new properties by using ApplicationUser instead the base IdentityUser.

Are controller factories neccessary when using Ninject in ASP.NET mvc 4

I am at a loss of what to do with the multitude of documentation available through google in .net as regards using Ninject with asp.net mvc 4
First of all, i want to know if Controller factories are neccessary in asp.net.
Also, is constructor injection really the only way we can do dependency injection with MVC 4 because property injection and method injection does not seem to work when i use them with my controllers
I am not an expert on Ninject but as far as i know, i am only using it to link my DataSource Interface and my EfDb Class to the rest of my application.
If you need a good book that has a Real Application built around Ninject try:
Pro ASP.NET MVC 3 Framework, Third Edition
or
Pro Asp.Net Mvc 4
There are very few lines of code i am usually concerned with
public class 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()
{
ninjectKernel.Bind<IDataSource>().To<EfDb>();
}
}
Then register your NinjectControllerFactory in Global.asax.cs with:
ControllerBuilder.Current.SetControllerFactory(new NinjectControllerFactory());
As you can see, this class use Method Injection using private void AddBindings(). This makes it very easy if you are following Test Driven Development (TDD)
See the documentation here:
https://github.com/ninject/ninject.web.mvc/wiki/Dependency-injection-for-controllers, "The only thing that has to be done is to configure the Ninject bindings for its dependencies. The controller itself will be found by Ninject even without adding a binding."
NInject will automagically set up your controller dependencies (provided it has a binding for those types).

Resources