reactiveui / refit

The automatic type-safe REST library for .NET Core, Xamarin and .NET. Heavily inspired by Square's Retrofit library, Refit turns your REST API into a live interface.
https://reactiveui.github.io/refit/
MIT License
8.46k stars 744 forks source link

How to create custom refit attributes? #793

Closed Josrph closed 3 years ago

Josrph commented 4 years ago

am trying to create a custom refit attribute like this:

[AttributeUsage(AttributeTargets.Method)]
public class CustomGetAttribute : GetAttribute
{
    public CustomGetAttribute(string path) : base(path) { }
}
public interface ICustomerService
{
    [CustomGet("/TestMethod")]
    Task TestMethod();
}

but a warning appears in visual studio output window when building the project:

D:\source\repos\RefitApiTest\packages\Refit.4.8.14\build\net461\refit.targets(30,5): warning : warning RF001: Method ICustomerService.TestMethod either has no Refit HTTP method attribute or you've used something other than a string literal for the 'path' argument.

and the method fails to generate in RefitStubs.g.cs?

Task ICustomerService.TestMethod()
{
    throw new NotImplementedException("Either this method has no Refit HTTP method attribute or you've used something other than a string literal for the 'path' argument.");
}

is it possible to create custom refit attributes?

iashaik commented 4 years ago

I am also in a similar boat, and I attempted the same thing... and got that exception. I think this could be an easy fix.

We have strict no "magic strings" policy so either we make every path as constants or we create a custom Get attribute, and the actual route is shared file between Server and Client, and we use ApiController enum to direct the controller we want to call.

public class GetWithRouteAttribute : GetAttribute
    {
        public GetWithRouteAttribute(ApiControllers controller, string route) 
            : base($"/api/{controller.ToValueString()}/{route}")
        {
        }
    }

This would have been a very simple fix since we already share the route (constants) on server and client, instead we are forced to maintain another set of constants.

Josrph commented 4 years ago

thanks for the idea @iashaik , but i don't really have a problem with the shared route constant like you do, i already figured that out using the repository and unit of work pattern.

my problem is that am using routing by action name which means i have to include the action name every time above each method in the interface.

so to make development easier what am trying to do is create a custom attribute and somehow use reflection if possible to get the method name from the interface which is in my case the same one as the action name since am using routing by action name, and then include it with the route constant,

of course i couldn't do that because i'm stuck at the custom attribute part? but i am curious though as how you managed to create your own custom attribute without getting any exceptions?

in end, i just wish if refit had an easy way of doing this:

public interface ICustomerService
{
    [Get("/{action}?customerID={customerID}")]
    Task<decimal> GetCustomerByID(int customerID);
}

instead of this:

public interface ICustomerService
{
    [Get("/GetCustomerByID?customerID={customerID}")]
    Task<decimal> GetCustomerByID(int customerID);
}
jamiehowarth0 commented 4 years ago

This will need semantic analysis, cause it currently uses a SyntaxTree to read C# code, and the attribute names are hard-coded in InterfaceStubGenerator.cs. I'm going to set up a fork and start prototyping a Roslyn-based approach.

clairernovotny commented 3 years ago

Should be implemented in #1029

clairernovotny commented 3 years ago

Please try v6.0-preview.84 and file bugs as you come across them.

github-actions[bot] commented 1 year ago

This issue has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.