Invoking WCF service via ChannelFactory in MVC controller using Unity.Mvc5 - asp.net-mvc

I've following projects:
Poco (listing all the potential objects/dtos)
BusinessServices (contains all the logic and communicates with database)
WcfServices (calls into Business Services and return Pocos)
MVC5 (calls into WcfServices)
Now, I'm trying to invoke the WcfServices without using the Proxy, but using the ChannelFactory and initializing it via Unity, I'm getting the error: "No parameterless constructor defined for this object". Please help.
UnityConfig.cs
public static void RegisterComponents()
{
var container = new UnityContainer();
// Register WCF
container.RegisterType<IPersonService>(
new ContainerControlledLifetimeManager(),
new InjectionFactory((c) => new ChannelFactory<IPersonService>("WSHttpBinding_IPersonService").CreateChannel()));
DependencyResolver.SetResolver(new UnityDependencyResolver(container));
}
PersonController.cs
public class PersonController : Controller
{
private readonly IPersonService _personService;
public PersonController(IPersonService personService)
{
_personService = personService;
}
...
...
...
}

Related

One EF Core DbContext Multiple Application

How can I use one DbContext with multiple application?
I have a WCF application (Net TCP binding) interface and implementation works fine with the DbContext. There is a need for API from the same application and I don't want to enable Http Binding on the WCF because of configuration and I have so many contracts. so I decided to import the service into asp.net core 2 via DI it works fine but works connect to Db via DbContext always returning null.
DB Context:
public class AppDbContext : DbContext
{
public AppDbContext(DbContextOptions<AppDbContext> options) : base(options){}
public AppDbContext()
{
}
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
if (!optionsBuilder.IsConfigured)
{
optionsBuilder.UseSqlServer(#"Server=.\;Database=Database;Trusted_Connection=True;MultipleActiveResultSets=true");
}
}
}
Service implementation
public partial class GeneralService : IGeneralService, IDisposable
{
protected readonly AppDbContext Db = new AppDbContext();
public void Dispose()
{
Db.Dispose();
}
}
Asp.net core Start Up
public void ConfigureServices(IServiceCollection services)
{
const string connection = #"Server=.\;Database=Database;Trusted_Connection=True;MultipleActiveResultSets=true";
services.AddDbContext<AppDbContext>(options => options.UseSqlServer(connection));
services.AddSingleton<IGeneralService,GeneralService>();
services.AddMvc()
.AddJsonOptions(options => options.SerializerSettings.ContractResolver = new Newtonsoft.Json.Serialization.DefaultContractResolver());
}
what am I doing wrong, what can I do I really don't want to use Proxy
connect to Db via DbContext always returning null.
I think that might be down to the fact that you're creating the DB context directly in the service class. You can/should inject your DbContext into your service instead. Something like:
public partial class GeneralService : IGeneralService, IDisposable
{
protected readonly AppDbContext Db;
public GeneralService(AppDbContext db)
{
Db = db;
}
// ... etc...
}
Further, since you're providing a connection string to the db in your Startup.cs you don't need the OnConfiguring method in your db context.
Finally, services shouldn't be singletons if they're using EF. See this answer which recommends the Request scope.

Autofac failing to pickup in Web API and OWIN

I'm trying to setup a project that uses both MVC and Web API via OWIN and I'm having trouble getting Autofac to take a effect.
Here's how I'm initializing Web API:
public partial class Startup
{
public static void ConfigureWebApi(IAppBuilder app)
{
var config = BuildHttpConfiguration();
var container = AutoFacConfig.BuildContainer();
config.DependencyResolver = new AutofacWebApiDependencyResolver(container);
app.UseAutofacMiddleware(container);
app.UseAutofacWebApi(config);
app.UseWebApi(config);
}
private static HttpConfiguration BuildHttpConfiguration()
{
var config = new HttpConfiguration();
// Response formatter config
config.Formatters.Remove(
GlobalConfiguration.Configuration.Formatters.XmlFormatter);
config.Formatters.JsonFormatter.SerializerSettings.ContractResolver =
new CamelCasePropertyNamesContractResolver();
// Setup Web API error reporting
var customErrors = (CustomErrorsSection)ConfigurationManager.GetSection("system.web/customErrors");
IncludeErrorDetailPolicy errorDetailPolicy;
switch (customErrors.Mode)
{
case CustomErrorsMode.RemoteOnly:
errorDetailPolicy
= IncludeErrorDetailPolicy.LocalOnly;
break;
case CustomErrorsMode.On:
errorDetailPolicy
= IncludeErrorDetailPolicy.Never;
break;
case CustomErrorsMode.Off:
errorDetailPolicy
= IncludeErrorDetailPolicy.Always;
break;
default:
throw new ArgumentOutOfRangeException();
}
config.IncludeErrorDetailPolicy = errorDetailPolicy;
config.MapHttpAttributeRoutes();
SwaggerConfig.ConfigureSwagger(config);
return config;
}
}
The BuildContainer() method looks like the following. This method is used to build the container for both MVC and Web API:
public static IContainer BuildContainer()
{
var builder = new ContainerBuilder();
// Register your MVC controllers.
builder.RegisterControllers(typeof(MvcApplication).Assembly)
.PropertiesAutowired();
builder.RegisterApiControllers(typeof(MvcApplication).Assembly);
// OPTIONAL: Register model binders that require DI.
builder.RegisterModelBinders(Assembly.GetExecutingAssembly());
builder.RegisterModelBinderProvider();
// OPTIONAL: Register web abstractions like HttpContextBase.
builder.RegisterModule<AutofacWebTypesModule>();
// OPTIONAL: Enable property injection in view pages.
builder.RegisterSource(new ViewRegistrationSource());
// OPTIONAL: Enable property injection into action filters.
builder.RegisterFilterProvider();
// Bind the core types
Core.Infrastructure.AutoFacConfig.BuildContainer(builder);
builder.RegisterType<Postal.EmailService>().As<Postal.IEmailService>();
// Effectively auto-wires the anything with an interface within Web assembly infrastructure folder
builder.RegisterAssemblyTypes(typeof(IJwtHelper).Assembly)
.Where(t => t.Namespace != null && t.Namespace.StartsWith("MyApp.Web.Infrastructure") && t.GetInterfaces().Any())
.AsImplementedInterfaces()
.InstancePerLifetimeScope();
// Set the dependency resolver to be Autofac.
return builder.Build();
}
I have Web API controllers setup in an area and I had everything working with standard MVC controllers. I would like to use Web API controllers for where it's appropriate, but every time I try to request a controller based on ApiController I get the error:
An error occurred when trying to create a controller of type 'XxxController'. Make sure that the controller has a parameterless public constructor.
-- Edit --
The API area config looks like the following. (Side note: I know this isn't the "proper" way to configure Web API. I include the {action} because I feel there are too many controller files otherwise.)
public class ApiAreaRegistration : AreaRegistration
{
public override string AreaName
{
get { return "Api"; }
}
public override void RegisterArea(AreaRegistrationContext context)
{
context.Routes.MapHttpRoute(
"Api_default",
"Api/{controller}/{action}/{id}",
new { action = "Index", id = UrlParameter.Optional }
);
}
}
The authentication controller looks like this:
public class AuthenticationController : MyAppApiJwtController
{
private readonly IUserRepository _userRepository;
private readonly IAppSettingsHelper _appSettingsHelper;
private readonly IJwtHelper _jwtHelper;
private readonly IDeviceRepository _deviceRepository;
private readonly IINLDataService _inlDataService;
public AuthenticationController(IUserRepository userRepository, IAppSettingsHelper appSettingsHelper, IJwtHelper jwtHelper, IDeviceRepository deviceRepository, IINLDataService inlDataService)
{
_userRepository = userRepository;
_appSettingsHelper = appSettingsHelper;
_jwtHelper = jwtHelper;
_deviceRepository = deviceRepository;
_inlDataService = inlDataService;
}
[HttpPost]
[AllowAnonymous]
public LoginResponseModel Login(LoginModel model)
{
...
}
}
The MyAppApiJwtController looks like this:
public class MyAppApiJwtController : ApiController
{
internal IAuthenticationManager AuthenticationManager
{
get { return Request.GetOwinContext().Authentication; }
}
private JwtUserIdentity _currentJwtUser;
public JwtUserIdentity CurrentJwtUser
{
get
{
if (_currentJwtUser != null)
return _currentJwtUser;
if (User == null)
return null;
_currentJwtUser = new JwtUserIdentity((ClaimsIdentity)User.Identity);
return _currentJwtUser;
}
}
}
-- Edit 2 --
The URL I'm attempting to use is http://localhost:20630/api/authentication/login
-- Edit 3 --
The MVC configuration looks like the following. This is called just before the Web API configuration:
public partial class Startup
{
public static void ConfigureMvc()
{
AreaRegistration.RegisterAllAreas();
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
MvcConfig.RegisterRoutes(RouteTable.Routes);
MvcConfig.ValueConfig();
BundleConfig.RegisterBundles(BundleTable.Bundles);
AutomapperConfig.Configure();
JsonConfig.Configure();
AutoFacConfig.ConfigureContainer();
}
}
ASP.NET Web API does not support MVC areas by default.
This code:
public class ApiAreaRegistration : AreaRegistration
{
public override string AreaName
{
get { return "Api"; }
}
public override void RegisterArea(AreaRegistrationContext context)
{
context.Routes.MapHttpRoute(
"Api_default",
"Api/{controller}/{action}/{id}",
new { action = "Index", id = UrlParameter.Optional }
);
}
}
Will instruct the framework to map any route starting with Api to MVC controllers, but, at the same time, such controllers exists only for Web API. This conflict directly relates to the exception thrown when the Dependency Resolver tries to create an instance of the controller (the exception message may be misleading).
What could be happening:
MVC is executed first, and tries to map your route api/authentication/login. This URI matches your AreaRegistration, so it will try to route the request to the AuthenticationController inside your Api area.
MVC asks the Dependency Resolver to create an instance of the above controller, that must inherit from Controller (that's because we are in the MVC context).
The resolver does not have a registration for a MVC Controller that is called AuthenticationController (the AuthenticationController inherits from ApiController), and it returns null (because that's the expected behavior of the IServiceProvider.GetService method).
MVC then reverts to its default implementation for creating the controller, but finds that AuthenticationController class does not have a parameterless constructor. An exception is thrown.
Please try by removing this area declaration: it is not useful (add your api prefix inside RoutePrefix or Route attributes for your controllers/actions) and works only for MVC, while you are defining Web API as an OWIN middleware.
Reference:
ASP.Net WebAPI area support

Refresh DbContext

I have created a project that uses Entity Framework 6. This project is a data layer that is used in multiple other projects, for example an MVC website and a Web API.
When a user changes something in the MVC website, it is stored through the data layer in the database. But the Web API project does not detect these changes.
My DbContext is injected in the controllers with Ninject. I tried Disposing the DbContext in the controller's Dispose method, which didn't work. Should I Refresh() the database context after it has been injected in the controller's constructor? Or is there another way to keep the DbContext in sync with the database?
Fwiw, here is the OWIN Startup class:
public class Startup
{
public void Configuration(IAppBuilder app)
{
HttpConfiguration config = new HttpConfiguration();
WebApiConfig.Register(config);
config.DependencyResolver = new NinjectResolver(NinjectWebCommon.CreateKernel());
app.UseWebApi(config);
}
}
And here is the Ninject code:
public static class NinjectWebCommon
{
public static IKernel CreateKernel()
{
var kernel = new StandardKernel();
kernel.Bind<Func<IKernel>>().ToMethod(ctx => () => new Bootstrapper().Kernel);
kernel.Bind<IHttpModule>().To<HttpApplicationInitializationHttpModule>();
GlobalConfiguration.Configuration.DependencyResolver = new WebApiContrib.IoC.Ninject.NinjectResolver(kernel);
// Register Services:
kernel.Bind<MyDbContext>().To<MyDbContext>().InRequestScope().WithConstructorArgument("disableOrgFilter", true);
return kernel;
}
}

What time a instance of an object created and assigned in dependency injection

Suppose we have a controller in MVC,like to this:
public class HomeController : Controller
{
IProductService _productService;
ICategoryService _categoryService;
IUnitOfWork _uow;
public HomeController(IUnitOfWork uow, IProductService productService, ICategoryService categoryService)
{
_productService = productService;
_categoryService = categoryService;
_uow = uow;
}
// ...
}
we use StructureMap for Dependency Injection,and now in Global..asax.cs we have a code like to this:
...
ObjectFactory.Initialize(x =>
{
x.For<IUnitOfWork>().HttpContextScoped().Use(() => new EFCodeFirstContext());
x.ForRequestedType<ICategoryService>().TheDefaultIsConcreteType<EfCategoryService>();
x.ForRequestedType<IProductService>().TheDefaultIsConcreteType<EfProductService>();
});
...
Now my Question is:
for example what time a instance of EfCategoryService be created and assigned to _categoryService?
1- any time we use _categoryService in any method in this controller?
OR
2-Immediately when a request to this controller sended? for example,
www.sitename.com/Home
or
www.sitename.com/Home/News
You should let ASP .NET MVC know that you're using StructureMap for dependency injection.
You can do it by providing an IControllerFactory
Before wiring the routing (in the begining of your program) use this code-
ControllerBuilder.Current.SetControllerFactory(new StractureMapControllerFactory());
Where StructureMapControllerFactory will provide the implementation to use the DI container when instantiating Controllers
I've never done it with StructureMap but I guess someone has already implemented the ContorllerFactory for StructureMap.

MVC 3 CookieTempDataProvider and Ninject IOC

I am trying to use the CookieTempDataProvider in MVC 3 futures assembly. I believe I have "wired" it up successfully using ninject. Below is the code from my app_start.cs file:
[assembly: WebActivator.PreApplicationStartMethod(typeof(Web.AppStart), "Start")]
namespace Web {
public static class AppStart {
public static void RegisterServices(IKernel kernel) {
kernel.Bind<ITempDataProvider>().To<CookieTempDataProvider>();
}
public static void Start() {
// Create Ninject DI Kernel
// IKernel kernel = new StandardKernel();
IKernel kernel = Container;
// Register services with our Ninject DI Container
RegisterServices(kernel);
// Tell ASP.NET MVC 3 to use our Ninject DI Container
DependencyResolver.SetResolver(new NinjectServiceLocator(kernel));
}
static IKernel _container;
public static IKernel Container
{
get
{
if (_container == null)
_container = new StandardKernel();
return _container;
}
}
However, when I access my page that uses TempData, I get the this error indicating that it is still trying to use the SessionTempDataProvider:
Server Error in '/' Application.
The SessionStateTempDataProvider class requires session state to be enabled.
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.
Exception Details: System.InvalidOperationException: The SessionStateTempDataProvider class requires session state to be enabled.
I must be missing something and I can't figure out what it is. Any help would be most appreciated.
Many Thanks
I've only been able to get this to work with the BaseController approach. The controller creation processes does't ask Ninject for a ITempDataProvider.
public class BaseController : Controller
{
protected override ITempDataProvider CreateTempDataProvider()
{
return new CookieTempDataProvider(HttpContext);
}
}
Extend the controller class
public static void SetMessage(this Controller controller, String message)
{
controller.TempData["Messag"] = message;
}
Then you can use it like this:
public ActionResult Save()
{
//Validation...
Save(Foo);
this.SetMessage("Item saved successfully");
return Redirect("/Site");
}
No number three :)

Resources