Страницы справки ASP Web API - ссылки на другие страницы

1 ответ

Решение

Мне удалось написать что-то, что правильно конвертирует ссылки.

Схема:

В конструкторе контроллера справки создайте новое сопоставление Lazy IDictionary между строками, найденными в скрипте (например, M:Api.Method.Description(System.String) и ассоциированным ApiDescription.

        _methodReferences = new Lazy<IDictionary<string, ApiDescription>>(() => {
            var dictionary = new Dictionary<string, ApiDescription>();

            var apiExplorer = new ApiExplorer(config);

            foreach (var apiDescription in apiExplorer.ApiDescriptions)
            {
                var descriptor = apiDescription.ActionDescriptor as ReflectedHttpActionDescriptor;
                if (descriptor != null)
                {
                    var methodName = string.Format(
                        @"M:{0}.{1}({2})",
                        descriptor.MethodInfo.DeclaringType.FullName,
                        descriptor.MethodInfo.Name,
                        string.Join(@",",descriptor.GetParameters().Select(x => x.ParameterType.FullName))
                        );
                    dictionary[methodName] = apiDescription;
                }

            }
            return dictionary;
        });

Передайте это ленивым различным моделям, которые поддерживают страницы (вам может понадобиться создать дополнительные модели). Я дал им всем базовый класс со следующим кодом:

public abstract class HelpPageModelBase
{
    private static Regex _seeRegex = new Regex("<see cref=\"([^\"]+)\" />");
    private readonly Lazy<IDictionary<string, ApiDescription>> _methodReferences;

    protected HelpPageModelBase(Lazy<IDictionary<string, ApiDescription>> methodReferences)
    {
        _methodReferences = methodReferences;
    }

    protected HelpPageModelBase(HelpPageModelBase parent)
    {
        _methodReferences = parent._methodReferences;
    }

    public string ParseDoc(string documentation, UrlHelper url)
    {
        if (documentation == null)
        {
            return null;
        }
        return _seeRegex.Replace(documentation,
                                 match => {
                                     if (_methodReferences.Value.ContainsKey(match.Groups[1].Value))
                                     {
                                         var descriptor = _methodReferences.Value[match.Groups[1].Value];

                                         return string.Format(@"<a href='{0}'>{1} {2}</a>",
                                                              url.Action("Api",
                                                                         "Help",
                                                                         new {
                                                                             apiId = descriptor.GetFriendlyId()

                                                                         }),
                                                              descriptor.HttpMethod.Method,
                                                              descriptor.RelativePath
                                             );
                                     }
                                     return "";
                                 });
    }
}

В любом месте во взглядах, которые имели api.Documentation.Trim() - или же Html.Raw(api.Documentation) если вы уже следили за страницей справки Web Api - не экранируйте html в документации xml - теперь вы переносите ее, чтобы она стала

@Html.Raw(Model.ParseDoc(api.Documentation, Url))

Вы обнаружите, что для этого вам нужно сделать так, чтобы различные ModelDescription наследовали от HelpPageModelBase - и передавать им родительские модели API (или Lazy, если проще), но в конце концов это работает.

Я не особенно доволен этим решением; вам может оказаться проще иметь какую-то статическую форму метода ParseDoc, которая использует конфигурацию Http по умолчанию для генерации Lazy (но из-за других расширений, которые я сделал, это не работает для моего случая). Если вы видите лучшие способы сделать это, пожалуйста, поделитесь! Надеюсь, это даст вам отправную точку.

Другие вопросы по тегам