I have decorated my service interface with Http Verb Attributes, but is not working.
Every method is treated as Post verb.
I'm using AspNetCore 1.1 and Abp packages 2.3.0
public interface ISettlementAppService : IApplicationService
{
Task<PagedResultDto<SettlementListDto>> GetPaged(GetSettlementInput input);
[HttpDelete]
Task Cancel(EntityDto<string> input);
}
For AspNet Core, add these attributes to the application service class, not to interface. Because they are handled by AspNet Core MVC (not by ABP) and it does not know about interfaces.
From the documentation (https://aspnetboilerplate.com/Pages/Documents/AspNet-Core#controllers):
Note: Previously, dynamic web api system was requiring to create service interfaces for application services. But this is not required for ASP.NET Core integration. Also, MVC attributes should be added to the service classes, even you have interfaces.
Do it like this;
public class SettlementAppService : ISettlementAppService
{
[HttpDelete]
Task Cancel(EntityDto<string> input){
//...
}
}
Related
I have downloaded template and creating sample task application.
From below reference I found Web API auto generated from my task service class.
Dynamic web api generation
So how can I stop this behaviour or make changes in this behavior.
You can easily disable an application service to expose its methods as Web API actions.
Just use [RemoteService(false)] attribute on application service class or application service interface.
[RemoteService(IsEnabled = false)]
public class UserAppService : ApplicationService, IUserAppService
{
}
for mass operation, use #aaron's method.
Comment out the lines mentioned on that page.
ASP.NET MVC 5
// Configuration.Modules.AbpWebApi().DynamicApiControllerBuilder
// .ForAll<IApplicationService>(typeof(AbpProjectNameApplicationModule).Assembly, "app")
// .Build();
https://github.com/aspnetboilerplate/module-zero-template/blob/c0d7f0433d573a8207b27f817e1d188c215f1e50/src/AbpCompanyName.AbpProjectName.WebApi/Api/AbpProjectNameWebApiModule.cs#L17-L19
ASP.NET Core
// Configuration.Modules.AbpAspNetCore()
// .CreateControllersForAppServices(
// typeof(AbpProjectNameApplicationModule).GetAssembly()
// );
https://github.com/aspnetboilerplate/module-zero-core-template/blob/bb9d5aab6e5047d6d22d49831b473c0b3329b499/aspnet-core/src/AbpCompanyName.AbpProjectName.Web.Core/AbpProjectNameWebCoreModule.cs#L44-L47
I have created a DTO which implements IInputDTO.
public class CreateUserModel : IInputDto
When I receive a service call on my web api layer it doesn't seem to validate the DTO as it just goes through the flow of the service method
public async Task<HttpResponseMessage> Create(CreateUserModel createUserRequest)
I'm running ASP.NET Boilerplate 0.8.3
The support for ASP.NET boilerplate has answered me that this is currently not possible. Only classes which implement the IApplicationService are currently able to do this.
Link to issue on ASP.NET Boilerplate's issue page
In normal ASP.MVC projects we configure the dependency resolver with Unity and the Unity.Mvc3 package from http://unitymvc3.codeplex.com/
We have this test service registered with a HierarchicalLifetimeManager
container.RegisterType<ITestService, TestService>(new HierarchicalLifetimeManager());
And we hook up the container with Mvc in Global.asax.cs:
System.Web.Mvc.DependencyResolver.SetResolver(new Unity.Mvc3.UnityDependencyResolver(container));
And we run this test controller:
public class TestController : Controller
{
private readonly ITestService _service;
public TestController(ITestService service)
{
this._service = service;
}
public ActionResult Test()
{
var locatedService = System.Web.Mvc.DependencyResolver.Current.GetService<ITestService>();
if (_service == locatedService)
return View("Success - Same Service");//This is always the result in an MVC controller
else
throw new Exception("Failure - Different Service Located");//This is never the result in an MVC controller
}
}
However, on this project we are adding a number of WebAPI controllers.
We have this configuration in global.asax.cs (using http://unitywebapi.codeplex.com/ for now. But I am open to suggestions):
System.Web.Http.GlobalConfiguration.Configuration.DependencyResolver = new Unity.WebApi.UnityDependencyResolver(container);
We have created an ApiTestController similar to TestController inheriting from ApiController rather than from Controller.
However, the ApiTestController fails its test. I understand that the System.Web.Mvc.DependencyResolver class and the System.Web.Mvc.DependencyResolver.Current property are specific to Mvc. But does WebAPI have an equivalent?
System.Web.Http.GlobalConfiguration.Configuration.DependencyResolver.GetService does not work because the System.Web.Http.GlobalConfiguration.Configuration.DependencyResolver instance is the parent container that I configured. It is not the child controller that was used to inject the ITestService into the constructor.
This user seems to have a similar problem: http://unitywebapi.codeplex.com/discussions/359413
But I feel that this probably has more to do with ASP.NET's WebAPI than it has to do with Unity.
Thanks
After looking over the source of http://unitymvc3.codeplex.com/ and http://unitywebapi.codeplex.com/ I created this class:
public class MyUnityDependencyResolver : Unity.Mvc3.UnityDependencyResolver, System.Web.Http.Dependencies.IDependencyResolver
{
public MyUnityDependencyResolver(IUnityContainer container)
: base(container)
{
}
public System.Web.Http.Dependencies.IDependencyScope BeginScope()
{
return this;
}
public void Dispose()
{
Unity.Mvc3.UnityDependencyResolver.DisposeOfChildContainer();
}
}
Configuration in gobal.asax.cs:
var myResolver = new MyUnityDependencyResolver(container);
System.Web.Mvc.DependencyResolver.SetResolver(myResolver);
System.Web.Http.GlobalConfiguration.Configuration.DependencyResolver = myResolver;
Unity.Mvc3.UnityDependencyResolver uses HttpContext.Current.Items to manage child containers. MyUnityDependencyResolver may not be the most "correct" implementation of System.Web.Http.Dependencies.IDependencyResolver, but it seems to work so far.
I will mark this as the answer in a couple days if no one else has any better answers.
Unfortunately, when you call the GlobalConfiguration.Configuration.DependencyResolver.GetService, it completely ignores any scope and resolves using the outer non-child container which is around for the lifetime of the application. This is an issue with Web Api and makes it impossible to use constructor injection for per-request dependencies outside of controllers. Confusingly this is completely different behaviour from MVC as you say.
What you can do is use the GetDependencyScope() extension method off HttpRequestMessage. Anything you resolve using this will be in per request scope when using HierarchicalLifetimeManager in conjunction with Unity.WebApi. The request is available from action filters and handlers so may be a viable workaround.
Obviously this is pure service location rather than dependency injection which is far from ideal but I have not found another way to access per-request dependencies outside of controllers.
See this post for more info.
The DependencyResolver is not the right seam for dependency injection in ASP.NET WebAPI.
Mark Seemann has two really good posts on DI with WebAPI.
Dependency Injection and Lifetime Management with ASP.NET Web API
Dependency Injection in ASP.NET Web API with Castle Windsor
If you want to do it right you should have a look at them.
I have been Googling for hours and cant find an article that is exactly related to what I need.
I have a MVC4 site with the following layers:
Presentation layer (MVC4)
Business Layer
Data layer
I want to use the following provider:(installed using NuGet)
Install-Package Microsoft.AspNet.Providers
My question is more of an architectural one.
In my mind, I should install this (Microsoft.AspNet.Providers) in my data layer as it is code that talks to a membership database.
All the posts I can find, however, even by Hanselman just install it in the Presentation layer / MVC4.
I am very big on separation of concerns and am using dependency injection throughout my application.
Obviously I need the config for the provider in my web.config but want all the membership code in my data layer.
Any thoughts?
thanks
RuSs
PS. Would love to know the process of installing this in a data / repository layer using nuget. Slightly confused as to what DLLs Nuget is installing. If I install in my data layer, nuget doesnt update the MVC web.config.
The answer is quite simple actually: You should hide the providers behind an abstraction that you define in your business layer. This way you can write an adapter that implements this abstraction an wraps the provider and you can inject this adapter into your business layer using dependency injection. This way you will only have to reference the Microsoft.AspNet.Providers from your MVC4 project, and prevent any code from directly referencing the AspNet.Providers, which allows you to switch more easily later on.
Example:
// Define in business layer
public interface IAuthorizationService
{
bool bool IsCurrentUserInRole(string role);
}
public class SomeBusinessLayerCommand
{
private IAuthorizationService authorizer;
public SomeBusinessLayerCommand(
IAuthorizationService authorizer)
{
this.authorizer = authorizer;
}
public void SomeOperation()
{
if (this.authorizer.UserIsInRole("Admins"))
{
// some secret admin stuf
}
else
{
// some normal user stuf
}
}
}
And in your Presentation Layer you can define an adapter:
public class MembershipAdapter : IAuthorizationService
{
public bool IsCurrentUserInRole(string role)
{
return Roles.IsUserInRole(role);
}
}
And you can map IAuthorizationService to MembershipAdapter using your favorite DI container.
I am creating a MVC3 website that will expose a REST API using WCF Web API.
To register routes to the REST API I add code to the Global.asax similar to the code below.
routes.MapServiceRoute<RelationsService>("relations");
This works well enough but i need to use a DI approach to inject the dependencies that the Service depends on.
As you can see in the code above the MVC framework is creating the instance of the RelationsService but this should be done by the DI container.
Does anyone know how to configure MVC3 so that my own DI container is used for creating the instances of the Services?
You have to extend your current service registration call with an IHttpHostConfigurationBuilder that has been created with an IResourceFactory.
var configurationBuilder = HttpHostConfiguration.Create()
.SetResourceFactory(new ResourceFactory());
routes.MapServiceRoute<RelationsService>("relations", configurationBuilder);
Then if you for instance use StructureMap as preferred IoC/DI tool you can just ask for the service in the GetInstance method.
public class ResourceFactory : IResourceFactory
{
public object GetInstance(Type serviceType, InstanceContext instanceContext, HttpRequestMessage request)
{
return ObjectFactory.GetInstance(serviceType);
}
}