我已经编写了一个C#接口并将其编译为Contract.dll。 ASP.NET MVC网站(在这种情况下为客户端)和ASP.NET Web API服务引用了Contract.dll。
我在网站上使用Refit来致电服务。我尝试在Refit的Get属性和Web API的HttpGet属性中使用来自Contract.dll的常量来指示服务方法URL。这将使我可以在一个地方指定URL,并由客户端和服务对其进行引用。
客户
public static class WidgetServiceUrls
{
public const string ListByName = "/widget/list/{Name}";
}
public interface IWidgetService
{
// Refit requires a string literal URL, not a constant. Ensure the implementing service uses the same URL.
[Get(WidgetServiceUrls.ListByName)]
Task<List<Widget>> List(string Name);
}
服务
// TODO: Determine how to eliminate duplicate URL string in service controller action and interface method.
[HttpGet(WidgetServiceUrls.ListByName)]
public async Task<List<Widget>> List(string Name)
Refit在调用RestService.For(httpClient)时引发异常:
IWidgetService看起来不像Refit接口。确保它有
至少具有Refit HTTP方法属性和Refit的一种方法是
安装在项目中。
显然,Refit无法理解Get属性中的常量。如果我在两个地方都使用字符串文字,则代码将正确执行。但是,现在我在两个地方重复URL违反了DRY原则。
如何在Contract.dll中注释接口,以便Refit客户端和Web API服务方法使用相同的URL?
最佳答案
如何从interface属性获取URL?
public interface IWidgetService
{
[Get("/widget/list/{Name}")]
Task<List<Widget>> List(string Name);
}
private string GetUrl()
{
MethodInfo method = typeof(IWidgetService).GetMethod("List");
object[] attributes = method.GetCustomAttributes(true);
foreach (var attr in attributes)
{
GetAttribute attribute = attr as GetAttribute;
if (attribute != null)
{
return attribute.Path;
}
}
throw new Exception("Unable to get API URL");
}