I am trying to build a GitHub application that will handle webhook events and a few other things not related to GitHub. My app has a GitHub controller that should handle all webhook events, but the GH sends all this in one URL.
The way to tell what event we should process is by checking the 'X-GitHub-Event' header value, and I am looking for the most straightforward option to route based on this.
I wouldn't say I like having one #Post() route and using logic inside the method to check the header and call proper service; this way, the controller's method would become huge.
What I am looking for is something like this:
#Controller('github')
public class GitHubController {
#Post()
#GitHubEvent('pull_request')
public processPR() {...}
#Post()
#GitHubEvent('comment')
public processComment() {...}
}
Related
I’m trying to make a POST request via Guzzle to a Yii controller but getting a "Bad Request #400". I thought when I don’t use behaviours() the controller is automatically accessible to all kinds of requests, but nope. How I can solve this? What would be best practice for CURL/Guzzle requests in Yii2?
class ImportController extends yii\web\Controller {
public function actionIndex() {
return 'OK';
}
}
You should create a rest controller instance (yii\rest\ActiveController) and implement authentication for it as described here: https://www.yiiframework.com/doc/guide/2.0/en/rest-authentication
That is probably the correct approach to your use case, and you would not have to deal with CSRF.
I'm in the process of deprecating an old API and want two (or multiple) requests to call the same endpoint. Something like this:
#Get('/request') // call endpoint with this request
#Get('/otherRequest') // or with this request
test() {
// do something
}
Clearly another way to do this would be to create another endpoint and use a service to share the functionality, but I am curious if this is possible as it would make the process easier to implement.
#Get(['/request', '/otherRequest'])
test() {
// do something
}
tip: inspect the TS types of #Get() ^^
I'm currently making a library that interacts with a particular API that requires an oAuth OIDC connection/token and I'd like to make something that makes that particular part easier for users of this library so they don't need all this custom code.
What is this currently called and is there an example of code?
I ask because from trying to get this work, the documentation is ALL OVER THE PLACE. It looks like this particular process has undergone significant changes multiple times as things went on from before netcore to netcore2 and now netcore31.
Both AddAuthentication and AddOpenIdConnect are extension methods.
An extension method allows you to "add" methods to a type without having to modify the type directly - the methods aren't actually added to the type, but we can call them as if they had been. This is useful in situations where you'd like to extend the behaviour of a class created by a third party but don't have access to the source code.
As for what the particular pattern in question is, whilst there is no canonical name, it's merely a way of encapsulating the configuration of services and dependencies for your application.
AddAuthentication is an extension method of IServiceCollection, which is services type. AddAuthentication has a return type of AuthenticationBuilder, and AddOpenIdConnect is an extension method for AuthenticationBuilder. This is the implementation of AddOpenIdConnect, but as you're looking to encapsulate the configuration, you could probably do something like this:
public static class OpenIdConnectExtensions
{
public static AuthenticationBuilder ConfigureOpendIdConnect(
this AuthenticationBuilder builder)
{
return builder.AddOpenIdConnect(options =>
{
options.SignInScheme = IdentityConstants.ExternalScheme;
// Do whatever else you need.
});
}
}
And call it as follows:
services
.AddAuthentication()
.ConfigureOpendIdConnect()
Middleware, on the other hand, is code that executes as part of a pipeline in order to process requests and responses. The middleware sits in the middle of receiving requests and sending responses, hence the name. This allows you do things such as always adding certain headers to responses without that logic being split across your application. As you correctly mentioned, you see these being applied via calls such as app.UseXyz().
This code run for every incoming request to check whether it contains a valid JWT token.
services.AddMvc(options =>
options.Filters.Add(typeof(JwtAttribute)));
That's what I want in most case, except for the first time (when the user is attempting to log in). Because it's running at every request, user can't log in.
I've tried to add an attribute on top of the login action, but it's still not working.
[HttpPost]
[AllowAnonymous]
public async Task<JsonResult> Login([FromBody]Credentials formData)
{
}
What should I do to override the OnActionExecuting in the startup class just in this one case, so that user can log in.
Thanks for helping
By using a custom filter, instead of the built-in authentication and authorization system, you will not be able to use [AllowAnonymous] here since that is directly linked to the auth framework.
What you can do is add additional metadata which you then check as part of your JwtAttribute filter. For example, create another attribute like so:
public class DisableJwtAttribute : Attribute, IFilterMetadata
{ }
You can now add this attribute to your controller action with [DisableJwt].
And inside of your JwtAttribute filter, you can now check for that filter’s existence to stop processing the request. E.g. if your filter is an authorization filter, that would look like this:
public async Task OnAuthorizationAsync(AuthorizationFilterContext context)
{
if (context.Filters.Any(item => item is DisableJwtAttribute))
return;
// filter is active
}
That being said, the better solution would be to embrace the authentication system and have your JWT validation be part of the normal authentication process. That way, you could actually benefit from all the authentication and authorization things within ASP.NET Core.
I have the following scenario in my ASP.NET MVC4 project using Razor Engine:
I have a view with at least 4 different forms.
I would like to handle all form POST under same action mapping.
Actually, the 4 forms post to different Route Mapping, as follow:
POST: /User/FilterRolesInUse/15
POST: /User/RemoveRoles/15
POST: /User/FilterRolesNotInUse/15
POST: /User/AddRoles/15
I would like to know if is it possible to handle all 4 form under the same Route Mapping, something where all form post to /User/Roles/15 and then the controller can distinguish which form was submitted. The concept is something like:
class UserController : Controller {
//
// POST: /User/Roles/
public ActionResult Roles(int? id, object form) {
return DelegateToFormLogic(id, form);
}
}
I just want to know if is it possible because I really want to keep URL consistent.
Any advice or suggestion are welcome.
I do not see any advantage to having a single action that performs multiple functions. In fact it will be confusing to anyone that has to support the code. I would get away from submitting forms and use Ajax methods in your web client (using JQuery ajax) to get the data you need for this view and for update/insert/delete actions. This way you do not have to post back the whole page to perform actions that will probably take place on just portions of the view which will result in a better performing page and a better user experience. Change your controller to a ASP.NET Web API controller and make those methods a REST API that uses consistent URL naming convention and use HTTP verbs to indicate the type of action being performed. You will end up 3 methods that serve the 4 you have now and it could look something like this (they correspond to the same order listed in the question).
GET: /api/Role/15?InUse=True
DELETE: /api/Role/15
GET: /api/Role/15?InUse=False
POST: /api/Role
Your controller would look like this.
class RoleController : ApiController {
public List<Role> Get(int id, boolean InUse) { ... }
public void Delete(int id) { ... }
public void Post(List<Role> roles) { ... }
}
This maintains a clear separation of concerns while also keeping a consistent and understandable URL convention.