我已经编写了一个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");
}

10-08 13:42