2011-04-14 13 views
6

Con .net 4.0/Preview kit 2, podemos generar páginas de ayuda para WCF REST.¿Cómo generar documentación para Asp.Net MVC?

¿Hay alguna forma en que podamos hacer lo mismo para MVC?

www.somewebsite.com/search/help

puedo crear páginas de ayuda (vistas) y exponerlos.

Puedo generar el esquema XSD y escupir como xml.

¿Alguna otra orientación/sugerencia?

Quiero generar algo similar a esto.

UriTemplate http://somewebsite.com/Search/

método PUT

Formato de respuesta XML

esquema de respuesta http://somewebsite.com/help/response/schema

Ejemplo de respuesta http://somewebsite.com/help/response/example

Actualización:

Pude crear documentación usando el código siguiente.

Route : somewebsite.com/Media/ 
HelpRoute : somewebsite.com/Media/Help (Append help to the parent route) 

Add routes accordingly. See below example. 

routes.MapRoute("Search", 
      "Search/Quick/", 
      new { controller = "Search", action = "Search" }, 
      new { httpMethod = new HttpMethodConstraint("PUT") } 
      ); 

     routes.MapRoute("SearchHelp", 
      "Search/Quick/Help", 
      new { controller = "Search", action = "Search" }, 
      new { helpConstraint = new HelpConstraint { Help = true, SampleType = typeof(Search) } } 
     ); 

public class HelpResult : ViewResult 
{ 
    private string HelpPage { get; set; } 
    private string folderName = "HelpFiles"; 
    private HttpServerUtilityBase server { get; set; } 
    private Type sampleType { get; set; } 
    private string schemaName { get; set; } 

    const string htmlFormat = 
      @" 
     <html> 
     <head> 
      <title>Help</title> 
     </head> 
     <body>   

     <li>URL - {0}</li> 
     <li>Verb - {1}</li> 
     {2} 

     </body> 
     </html> 
     "; 

    public override void ExecuteResult(ControllerContext context) 
    { 
     server = context.HttpContext.Server; 
     StringBuilder parentUrl = new StringBuilder(); 
     var data = context.RouteData.Route.GetRouteData(context.HttpContext); 

     //Getting requested route url. 
     string url = ((Route)(data.Route)).Url; 

     //Getting parent route from requested route url by removing "Help" from the route. 
     string newUrl = url.Substring(0, url.Length - 4); 
     parentUrl.Append("/" + newUrl); 

     sampleType = data.GetSampleType(); 
     var validVerbs = GetValidVerbs(MakeAppRelative(parentUrl.ToString())); 
     CreateSchema(sampleType, true); 
     HelpPage = string.Format(htmlFormat, newUrl, validVerbs, CreateInputSampleText()); 
     context.HttpContext.Response.Output.Write(HelpPage); 
    } 

    private string CreateInputSampleText() 
    { 
     if (sampleType != null && !string.IsNullOrEmpty(sampleType.Name)) 
     { 
      string sampleText = 
       @"<li>Input Sample Xml - <a href='\HelpFiles\{0}.xml'>Click Here</a></li>   
     <li>Input Sample Json - <a href='\HelpFiles\{0}.txt'>Click Here</a></li> 
     <li>Input Schema - <a href='\HelpFiles\{1}'>Click Here</a></li>"; 
      sampleText = string.Format(sampleText, sampleType.Name, schemaName); 
      return sampleText; 
     } 

     return string.Empty; 
    } 

    private static string MakeAppRelative(string url) 
    { 
     if (!url.StartsWith("~")) 
     { 
      if (!url.StartsWith("/")) 
       url = "~/" + url; 
      else 
       url = "~" + url; 
     } 
     return url; 
    } 

    private static string GetValidVerbs(string Url) 
    { 
     StringBuilder validVerbs = new StringBuilder(); 
     var httpMethodOptions = new[] { "GET", "POST", "PUT", "DELETE", "HEAD" }; 
     foreach (var httpMethodOption in httpMethodOptions) 
     { 
      var fakeContext = new FakeHttpContext(MakeAppRelative(Url), httpMethodOption); 
      foreach (Route route in RouteTable.Routes) 
      { 
       var rd = route.GetRouteData(fakeContext); 
       if (rd != null) 
       { 
        bool errorControllerApplied = route.IsErrorController(); 
        if (!errorControllerApplied) 
        { 
         validVerbs.Append(httpMethodOption); 
        } 
       } 
      } 
     } 

     return validVerbs.ToString(); 
    } 

    private void CreateFile(Type type, Stream stream) 
    { 
     using (Stream inputStream = stream) 
     { 
      schemaName = sampleType + "Schema.xml"; 
      string folder = Path.GetFullPath(Path.Combine(server.MapPath("~"), folderName)); 
      string file = Path.Combine(folder, schemaName); 
      if (!Directory.Exists(folder)) 
       Directory.CreateDirectory(folder); 

      using (FileStream fileStream = new FileStream(file, FileMode.Create)) 
      { 
       byte[] fileContent = new byte[inputStream.Length]; 
       inputStream.Read(fileContent, 0, fileContent.Length); 
       fileStream.Write(fileContent, 0, fileContent.Length); 
       fileStream.Flush(); 
      } 
     } 
    } 

    private void CreateSchema(Type type, bool isXmlSerializerType) 
    { 
     System.Collections.IEnumerable schemas; 
     if (isXmlSerializerType) 
     { 
      XmlReflectionImporter importer = new XmlReflectionImporter(); 
      XmlTypeMapping typeMapping = importer.ImportTypeMapping(type); 
      XmlSchemas s = new XmlSchemas(); 
      XmlSchemaExporter exporter = new XmlSchemaExporter(s); 
      exporter.ExportTypeMapping(typeMapping); 
      schemas = s.GetSchemas(null); 
     } 
     else 
     { 
      XsdDataContractExporter exporter = new XsdDataContractExporter(); 
      exporter.Export(type); 
      schemas = exporter.Schemas.Schemas(); 
     } 
     using (MemoryStream stream = new MemoryStream()) 
     { 
      XmlWriterSettings xws = new XmlWriterSettings() { Indent = true }; 
      using (XmlWriter w = XmlWriter.Create(stream, xws)) 
      { 
       w.WriteStartElement("Schemas"); 
       foreach (XmlSchema schema in schemas) 
       { 
        if (schema.TargetNamespace != "http://www.w3.org/2001/XMLSchema") 
        { 
         schema.Write(w); 
        } 
       } 
      } 
      stream.Seek(0, SeekOrigin.Begin); 
      CreateFile(type, stream); 
     } 
    } 
public static class RouteDataExtensions 
{ 
    public static bool IsHelpConstraintApplied(this RouteData data) 
    { 
     if (data != null && data.Route != null) 
     { 
      var constraints = ((Route) (data.Route)).Constraints; 
      var helpConstraint = (from c in constraints.Values 
            where c.GetType().Equals(typeof (HelpConstraint)) 
            select c).FirstOrDefault(); 
      if (helpConstraint != null) 
      { 
       return true; 
      } 
     } 

     return false; 
    } 

    public static Type GetSampleType(this RouteData data) 
    { 
     if (data != null && data.Route != null) 
     { 
      var constraints = ((Route)(data.Route)).Constraints; 
      var helpConstraint = (from c in constraints.Values 
            where c.GetType().Equals(typeof(HelpConstraint)) 
            select c).FirstOrDefault(); 
      if (helpConstraint != null) 
      { 
       return ((HelpConstraint) helpConstraint).SampleType; 
      } 
     } 

     return null; 
    } 

    public static string GetMethodType(this RouteData data) 
    { 
     if (data != null && data.Route != null) 
     { 
      var constraints = ((Route) (data.Route)).Constraints; 
      var httpMethodConstraint = (from c in constraints.Values 
             where c.GetType().Equals(typeof (HttpMethodConstraint)) 
             select c).FirstOrDefault(); 
      if (httpMethodConstraint != null) 
      { 
       return ((HttpMethodConstraint) httpMethodConstraint).AllowedMethods.Single(); 
      } 
     } 

     return null; 
    } 

    public static bool IsErrorController(this Route data) 
    { 
     if (data != null) 
     { 
      var defaults = ((Route)(data)).Defaults; 
      var controllerName = (from c in defaults.Values 
             where c.ToString().Contains("Error") 
             select c).FirstOrDefault(); 
      if (controllerName != null) 
      { 
       return true; 
      } 
     } 

     return false; 
    } 

    public static RouteData GetRouteDataByUrl(this string url) 
    { 
     string httpMethod = "PUT"; 
     var fakeContext = new FakeHttpContext(MakeAppRelative(url), httpMethod); 
     return RouteTable.Routes.GetRouteData(fakeContext); 
    } 

    private static string MakeAppRelative(string url) 
    { 
     if (!url.StartsWith("~")) 
     { 
      if (!url.StartsWith("/")) 
       url = "~/" + url; 
      else 
       url = "~" + url; 
     } 
     return url; 
    } 
} 

public class HelpConstraint : IRouteConstraint 
{ 
    public bool Help { get; set; } 
    public Type SampleType { get; set; } 

    public bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection) 
    { 
     if(Help) 
     { 
      return true; 
     } 

     return false; 
    } 
} 

References 
http://stephenwalther.com/blog/archive/2008/08/03/asp-net-mvc-tip-29-build-a-controller-to-debug-your-custom-routes.aspx 
http://aspnet.codeplex.com/releases/view/24644 

Este código no está libre de errores. Por favor, publique mejoras si tiene alguna. Úselo bajo su propio riesgo.

+0

¿Está hablando de documentar su código (dll), si es así, yo personalmente uso Sandcastle, el html de salida, y luego puede volcarlo en su sitio web –

Respuesta

1

Probablemente ya hayas resuelto tu problema. De todos modos, creo que necesitas IApiExplorer. Eche un vistazo al this blog.

+0

Lone link se considera una respuesta pobre (ver [faq # eliminación]) ya que no tiene sentido por sí mismo y ** no se garantiza que el recurso objetivo esté vivo en el futuro **. [Sería preferible] (http://meta.stackexchange.com/q/8259) incluir aquí las partes esenciales de la respuesta y proporcionar el enlace de referencia. – j0k

Cuestiones relacionadas