I have custom class-based middleware like:
#Service()
export class MyMiddleware implements MiddlewareInterface<Context> {
constructor(private readonly service: Service) {}
async use({ info, context }: ResolverData<Context>, next: NextFn) {
// this.service.doSomeDbLogicHere()
return next();
}
}
#UseMiddleware(MyMiddleware)
#Mutation(() => User)
public async createuser() {}
I wonder how I can pass custom static values to my middleware, but still have other objects injected via DI.
You need to create a function that accepts a static value and return a middleware class.
Related
I am trying to get a dependency injected into the constructor of a custom authorization handler, but the AddAuthorization in asp.net is making it difficult.
Handler:
class MyHandler : AuthorizationHandler<MyRequirement>
{
readonly IDependent dependency;
public UserExistsHandler(IDependent dependency)
{
this.dependency = dependency;
}
protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, MyRequirement requirement)
{
context.Succeed(requirement);
}
}
Program.cs
builder.Services.AddSingleton<IAuthorizationHandler, MyHandler>();
builder.Services.AddAuthorization(config =>
{
config.AddPolicy("MyPolicy", policy =>
{
// how?
policy.AddRequirements(new )
});
});
According to official documentation this should be possible:
https://learn.microsoft.com/en-us/aspnet/core/security/authorization/dependencyinjection?view=aspnetcore-6.0
However, the signature for AddRequirements is not generic and requires me to pass an actual instance of the handler which I cannot do because I have no reference to the IServiceProvider in the config delegate.
https://github.com/dotnet/aspnetcore/blob/4faa84c9ddf8c9e9cc9e5b43ca15f090037c4b68/src/Security/Authorization/Core/src/AuthorizationPolicyBuilder.cs#L73
How do I register the handler without having to create a new instance to be registered which defeats the purpose of the DI I am trying to do?
It's not the handler that you need to pass to AddRequirements, but the an instance of MyRequirement.
builder.Services.AddAuthorization(config =>
{
config.AddPolicy("MyPolicy", policy =>
{
policy.AddRequirements(new MyRequirement());
});
});
I am trying to call a stateless service from Asp.Net Core Stateless API. I am not able to reach the methods in Stateless Service.
This is the Controller action method which will call the stateless service method.
// GET api/values
[HttpGet]
public async Task<string> GetAsync()
{
var repository = ServiceProxy.Create<IRepository>(
new Uri("fabric:/Application1/Stateless1"));
return await repository.GetSomething();
//return new string[] { "value1", "value2" };
}
This is the method in Stateless service.
internal sealed class Stateless1 : StatelessService, IRepository
{
public Stateless1(StatelessServiceContext context)
: base(context)
{ }
public async Task<string> GetSomething()
{
return await Task.FromResult("HELLO FROM SERVICE!");
}
}
And the listener code is
protected override IEnumerable<ServiceInstanceListener> CreateServiceInstanceListeners()
{
return this.CreateServiceInstanceListeners();
}
I am able to hit the controller Get method but it is struck at repository.GetSomething() method and not able to reach that method. I don't know what I am missing here.
Any pointers will be very helpful. Thanks in advance
Update:
Manifest file:
You need to change your CreateServiceInstanceListeners...
protected override IEnumerable<ServiceInstanceListener> CreateServiceInstanceListeners()
{
return this.CreateServiceRemotingInstanceListeners();
}
It needs the remoting listener as using the ServiceProxy is a remoting call.
So I want IIS to basically not do anything when certain urls are requested bacause I want react router to which I have rendered from serverside, to handle the request.
Used this link
I have created a middleware that checks each request. Now i dont know how to ignore or abort this request once I find the right urls.
public class IgnoreRouteMiddleware
{
private readonly RequestDelegate next;
// You can inject a dependency here that gives you access
// to your ignored route configuration.
public IgnoreRouteMiddleware(RequestDelegate next)
{
this.next = next;
}
public async Task Invoke(HttpContext context)
{
if (context.Request.Path.HasValue &&
context.Request.Path.Value!="/")
{
// cant stop anything here. Want to abort to ignore this request
}
await next.Invoke(context);
}
}
If you want to stop a request, just don't call next.Invoke(context), because this will call the next middleware in the pipeline. Not calling it, just ends the request (and the previous middlewares code after it's next.Invoke(context) will be processed).
In your case, just move the call to the else branch or just negate the if expression
public class IgnoreRouteMiddleware
{
private readonly RequestDelegate next;
// You can inject a dependency here that gives you access
// to your ignored route configuration.
public IgnoreRouteMiddleware(RequestDelegate next)
{
this.next = next;
}
public async Task Invoke(HttpContext context)
{
if (!(context.Request.Path.HasValue && context.Request.Path.Value!="/"))
{
await next.Invoke(context);
}
}
}
Also make sure to read the ASP.NET Core Middleware documentation for a better understanding on how middlewares work.
Middleware is software that is assembled into an application pipeline to handle requests and responses. Each component:
Chooses whether to pass the request to the next component in the pipeline.
Can perform work before and after the next component in the pipeline is invoked.
But if you want server-sided rendering, consider using Microsoft`s JavaScript/SpaServices library, which is already built in in the newer templates (ASP.NET Core 2.0.x) and register a fallback route such as.
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
routes.MapSpaFallbackRoute(
name: "spa-fallback",
defaults: new { controller = "Home", action = "Index" });
});
The new templates also come with support for hot module replacement
Is there a way I can access the current Requested URL in ASPCore 2.0 Middleware?
Is there something I can Inject?
HttpContext object will be passed to the Invoke method of your middleware. You can access the Request property on that.
You can use the GetDisplayUrl extension method or GetEncodedUrl extension method.
public Task Invoke(HttpContext context)
{
var url1 =context.Request.GetDisplayUrl();
var url2 = context.Request.GetEncodedUrl();
// Call the next delegate/middleware in the pipeline
return this._next(context);
}
These 2 extension methods are defined in Microsoft.AspNetCore.Http.Extensions namespace. So make sure you have a using statement to include the namespace
using Microsoft.AspNetCore.Http.Extensions;
Your middleware get HttpContext context which has
//
// Summary:
// /// Gets the Microsoft.AspNetCore.Http.HttpRequest object for this request. ///
public abstract HttpRequest Request { get; }
So you may get all needed info in next way:
app.Use(async (context, next) =>
{
//context.Request.Path
//context.Request.QueryString
...
await next.Invoke();
});
Example:
I have a Route file with an endpoint /something/cool:
$router->get('/something/cool', [
'uses' => 'MyController#myFunctionOne',
]);
And I have a Controller named MyController.
In MyController I have a function named myFunctionOne.
In the myFunctionOne parameter I have an injected service class named MyService.
MyService has a function that calls an external API callExternalApi().
Here's how my controller looks like:
class MyController
{
public function myFunctionOne(MyService $myService)
{
$myService->callExternalApi();
// do some other things..
}
}
On the other side I have a functional test:
class SomethingCoolTest extends TestCase
{
public function testSomethingCool()
{
// callin my Route Endpoint (real http call to my app)
$this->get('/something/cool', [])->response;
// do some assertions..
}
}
My question is: how can I mock the controller injected service, since it's calling an external service?
That was easier than I expected :D
First create a mocking helper function named mock:
public function mock($class)
{
$mock = \Mockery::mock($class);
$this->app->instance($class, $mock);
return $mock;
}
Then Mock any service you like, as follow:
$mimo = $this->mock(MyService::class);
$mimo->shouldReceive('callExternalApi')->once()->andReturn([
"anything" => "cool"
]);