public ContentResult GetAllRoutes()
        {
            StringBuilder nonSb = new StringBuilder();
            StringBuilder sb    = new StringBuilder();

            foreach (var endpoint in _dataSource.Endpoints)
            {
                ControllerActionDescriptor controllerActionDescriptor = endpoint.Metadata.GetMetadata <ControllerActionDescriptor>();
                if (controllerActionDescriptor == null)
                {
                    continue;
                }

                IODataRoutingMetadata metadata = endpoint.Metadata.GetMetadata <IODataRoutingMetadata>();
                if (metadata == null)
                {
                    AppendRoute(nonSb, endpoint);
                }
                else
                {
                    AppendRoute(sb, endpoint);
                }
            }

            string output = ODataRouteMappingHtmlTemplate.Replace("ODATACONTENT", sb.ToString(), StringComparison.OrdinalIgnoreCase);

            output = output.Replace("NONENDPOINTCONTENT", nonSb.ToString(), StringComparison.OrdinalIgnoreCase);

            return(base.Content(output, "text/html"));
        }
Пример #2
0
        public Task ApplyAsync(HttpContext httpContext, CandidateSet candidates)
        {
            if (httpContext == null)
            {
                throw new ArgumentNullException(nameof(httpContext));
            }

            // The goal of this method is to perform the final matching:
            // Map between route values matched by the template and the ones we want to expose to the action for binding.
            // (tweaking the route values is fine here)
            // Invalidating the candidate if the key/function values are not valid/missing.
            // Perform overload resolution for functions by looking at the candidates and their metadata.
            for (var i = 0; i < candidates.Count; i++)
            {
                ref CandidateState candidate = ref candidates[i];
                if (!candidates.IsValidCandidate(i))
                {
                    continue;
                }

                IODataRoutingMetadata metadata = candidate.Endpoint.Metadata.OfType <IODataRoutingMetadata>().FirstOrDefault();
                if (metadata == null)
                {
                    continue;
                }

                IHttpMethodMetadata httpMetadata = candidate.Endpoint.Metadata.GetMetadata <IHttpMethodMetadata>();
                if (httpMetadata == null)
                {
                    // Check the http method
                    if (metadata.HttpMethods != null && !metadata.HttpMethods.Contains(httpContext.Request.Method))
                    {
                        candidates.SetValidity(i, false);
                        continue;
                    }
                }

                ODataTemplateTranslateContext translatorContext =
                    new ODataTemplateTranslateContext(httpContext, candidate.Values, metadata.Model);

                try
                {
                    ODataPath odataPath = _translator.Translate(metadata.Template, translatorContext);
                    if (odataPath != null)
                    {
                        IODataFeature odataFeature = httpContext.ODataFeature();
                        odataFeature.PrefixName = metadata.Prefix;
                        odataFeature.Model      = metadata.Model;
                        odataFeature.Path       = odataPath;
                    }
                    else
                    {
                        candidates.SetValidity(i, false);
                    }
                }
                catch (Exception)
                {
                    candidates.SetValidity(i, false);
                }
            }
            public ContentResult GetAllRoutes()
            {
                StringBuilder nonSb = new StringBuilder();
                StringBuilder sb    = new StringBuilder();

                foreach (var endpoint in _dataSource.Endpoints)
                {
                    ControllerActionDescriptor controllerActionDescriptor = endpoint.Metadata.GetMetadata <ControllerActionDescriptor>();
                    if (controllerActionDescriptor == null)
                    {
                        continue;
                    }

                    IODataRoutingMetadata metadata = endpoint.Metadata.GetMetadata <IODataRoutingMetadata>();
                    if (metadata == null)
                    {
                        AppendNonODataRoute(nonSb, endpoint);
                        continue;
                    }

                    // controller and action details
                    StringBuilder action = new StringBuilder();
                    if (controllerActionDescriptor.MethodInfo.ReturnType != null)
                    {
                        action.Append(controllerActionDescriptor.MethodInfo.ReturnType.Name + " ");
                    }
                    else
                    {
                        action.Append("void ");
                    }
                    action.Append(controllerActionDescriptor.MethodInfo.Name + "(");
                    action.Append(string.Join(",", controllerActionDescriptor.MethodInfo.GetParameters().Select(p => p.ParameterType.Name)));
                    action.Append(")");
                    string actionName = controllerActionDescriptor.MethodInfo.Name;

                    sb.Append("<tr>");
                    sb.Append($"<td>{GetActionDesciption(controllerActionDescriptor)}</td>");

                    // http methods
                    string httpMethods = string.Join(",", metadata.HttpMethods);
                    sb.Append($"<td>{httpMethods.ToUpper()}</td>");

                    // template name
                    RouteEndpoint routeEndpoint = endpoint as RouteEndpoint;
                    if (routeEndpoint != null)
                    {
                        sb.Append("<td>~/").Append(routeEndpoint.RoutePattern.RawText).Append("</td></tr>");
                    }
                    else
                    {
                        sb.Append("<td>---NON RouteEndpoint---</td></tr>");
                    }
                }

                string output = ODataRouteMappingHtmlTemplate.Replace("{CONTENT}", sb.ToString());

                output = output.Replace("{NONENDPOINTCONTENT}", nonSb.ToString());

                return(base.Content(output, "text/html"));
            }
        private OpenApiDocument CreateDocument(string prefixName)
        {
            IDictionary <string, ODataPath> tempateToPathDict = new Dictionary <string, ODataPath>();
            ODataOpenApiPathProvider        provider          = new ODataOpenApiPathProvider();
            IEdmModel model = null;

            foreach (var endpoint in _dataSource.Endpoints)
            {
                IODataRoutingMetadata metadata = endpoint.Metadata.GetMetadata <IODataRoutingMetadata>();
                if (metadata == null)
                {
                    continue;
                }

                if (metadata.Prefix != prefixName)
                {
                    continue;
                }
                model = metadata.Model;

                RouteEndpoint routeEndpoint = endpoint as RouteEndpoint;
                if (routeEndpoint == null)
                {
                    continue;
                }

                // get rid of the prefix
                int    length            = prefixName.Length;
                string routePathTemplate = routeEndpoint.RoutePattern.RawText.Substring(length);
                routePathTemplate = routePathTemplate.StartsWith("/") ? routePathTemplate : "/" + routePathTemplate;

                if (tempateToPathDict.TryGetValue(routePathTemplate, out ODataPath pathValue))
                {
                    string method = GetHttpMethod(metadata, endpoint);
                    pathValue.HttpMethods.Add(method);
                    continue;
                }

                var path = metadata.Template.Translate();
                if (path == null)
                {
                    continue;
                }

                path.PathTemplate = routePathTemplate;
                provider.Add(path);

                string method1 = GetHttpMethod(metadata, endpoint);
                path.HttpMethods.Add(method1);
                tempateToPathDict[routePathTemplate] = path;
            }

            OpenApiConvertSettings settings = new OpenApiConvertSettings
            {
                PathProvider = provider,
                ServiceRoot  = BuildAbsolute()
            };

            return(model.ConvertToOpenApi(settings));
        }
Пример #5
0
        public IEnumerable <EndpointRouteInfo> GetAllRoutes()
        {
            if (_dataSource == null)
            {
                return(Enumerable.Empty <EndpointRouteInfo>());
            }

            IList <EndpointRouteInfo> routeInfos = new List <EndpointRouteInfo>();

            foreach (var endpoint in _dataSource.Endpoints)
            {
                RouteEndpoint routeEndpoint = endpoint as RouteEndpoint;
                if (routeEndpoint == null)
                {
                    continue;
                }

                ControllerActionDescriptor controllerActionDescriptor = endpoint.Metadata.GetMetadata <ControllerActionDescriptor>();
                if (controllerActionDescriptor == null)
                {
                    continue;
                }

                EndpointRouteInfo routeInfo = new EndpointRouteInfo();

                StringBuilder action = new StringBuilder();
                if (controllerActionDescriptor.MethodInfo.ReturnType != null)
                {
                    action.Append(controllerActionDescriptor.MethodInfo.ReturnType.Name + " ");
                }
                else
                {
                    action.Append("void ");
                }
                action.Append(controllerActionDescriptor.MethodInfo.Name + "(");
                action.Append(string.Join(",", controllerActionDescriptor.MethodInfo.GetParameters().Select(p => p.ParameterType.Name)));
                action.Append(")");

                routeInfo.ControllerFullName = controllerActionDescriptor.ControllerTypeInfo.FullName;
                routeInfo.ActionFullName     = action.ToString();
                routeInfo.Template           = routeEndpoint.RoutePattern.RawText;

                var httpMethods = GetHttpMethods(endpoint);
                routeInfo.HttpMethods = string.Join(",", httpMethods);

                IODataRoutingMetadata metadata = endpoint.Metadata.GetMetadata <IODataRoutingMetadata>();
                if (metadata == null)
                {
                    routeInfo.IsODataRoute = false;
                }
                else
                {
                    routeInfo.IsODataRoute = true;
                }

                routeInfos.Add(routeInfo);
            }

            return(routeInfos);
        }
Пример #6
0
        internal async Task HandleJsonEndpointsAsync(HttpContext context)
        {
            if (context == null)
            {
                throw Error.ArgumentNull(nameof(context));
            }

            List <EndpointRouteInfo> infos      = new List <EndpointRouteInfo>();
            EndpointDataSource       dataSource = context.RequestServices.GetRequiredService <EndpointDataSource>();

            foreach (var endpoint in dataSource.Endpoints)
            {
                ControllerActionDescriptor controllerActionDescriptor = endpoint.Metadata.GetMetadata <ControllerActionDescriptor>();
                if (controllerActionDescriptor == null)
                {
                    continue;
                }

                EndpointRouteInfo info = new EndpointRouteInfo
                {
                    DisplayName = endpoint.DisplayName,
                    HttpMethods = string.Join(",", GetHttpMethods(endpoint)),
                };

                // template name
                RouteEndpoint routeEndpoint = endpoint as RouteEndpoint;
                if (routeEndpoint != null)
                {
                    info.Template = routeEndpoint.RoutePattern.RawText;
                }
                else
                {
                    info.Template = "N/A";
                }

                IODataRoutingMetadata metadata = endpoint.Metadata.GetMetadata <IODataRoutingMetadata>();
                if (metadata == null)
                {
                    info.IsODataRoute = false;
                }
                else
                {
                    info.IsODataRoute = true;
                }

                infos.Add(info);
            }

            JsonSerializerOptions options = new JsonSerializerOptions()
            {
                WriteIndented = true
            };
            string output = JsonSerializer.Serialize(infos, options);

            context.Response.Headers["Content_Type"] = "application/json";
            await context.Response.WriteAsync(output).ConfigureAwait(false);
        }
Пример #7
0
 /// <summary>
 /// Execute for second pass for OData API description.
 /// </summary>
 /// <param name="context">The ApiDescriptionProviderContext.</param>
 public void OnProvidersExecuted(ApiDescriptionProviderContext context)
 {
     foreach (var action in context?.Actions)
     {
         IODataRoutingMetadata odataMetadata = action.EndpointMetadata.OfType <IODataRoutingMetadata>().FirstOrDefault();
         if (odataMetadata != null)
         {
             ApiDescription apiDes = context.Results.FirstOrDefault(r => r.ActionDescriptor == action);
             if (apiDes != null)
             {
                 apiDes.RelativePath = odataMetadata.TemplateDisplayName;
             }
         }
     }
 }
Пример #8
0
        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            else
            {
                app.UseExceptionHandler("/error");
            }

            app.UseHttpsRedirection();

            // Add the OData Batch middleware to support OData $Batch
            //app.UseODataBatching(); // call before "UseRouting"

            app.UseRouting();

            app.UseAuthentication();
            app.UseAuthorization();

            // Test middelware
            app.Use(next => context =>
            {
                var endpoint = context.GetEndpoint();
                if (endpoint == null)
                {
                    return(next(context));
                }

                IEnumerable <string> templates;
                IODataRoutingMetadata metadata = endpoint.Metadata.GetMetadata <IODataRoutingMetadata>();
                if (metadata != null)
                {
                    templates = metadata.Template.GetTemplates();
                }

                return(next(context));
            });

            //app.UseMiddleware<JwtMiddleware>();

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllers();
            });
        }
        private static string GetHttpMethod(IODataRoutingMetadata metadata, Endpoint endpoint)
        {
            string method = metadata.HttpMethods.FirstOrDefault();

            if (method != null)
            {
                return(method);
            }

            HttpMethodMetadata methodMetadata = endpoint.Metadata.GetMetadata <HttpMethodMetadata>();

            if (methodMetadata != null)
            {
                return(methodMetadata.HttpMethods.First());
            }

            throw new Exception();
        }
Пример #10
0
        private static RouteEndpoint CreateEndpoint(string template, IODataRoutingMetadata odataMetadata, params object[] more)
        {
            var metadata = new List <object>();

            if (odataMetadata != null)
            {
                metadata.Add(odataMetadata);
            }

            if (more != null)
            {
                metadata.AddRange(more);
            }

            return(new RouteEndpoint(
                       (context) => Task.CompletedTask,
                       RoutePatternFactory.Parse(template),
                       0,
                       new EndpointMetadataCollection(metadata),
                       $"test: {template} - { odataMetadata?.Prefix ?? ""}"));
        }
Пример #11
0
        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }

            app.UseODataBatching();

            app.UseRouting();

            // Test middelware
            app.Use(next => context =>
            {
                var endpoint = context.GetEndpoint();
                if (endpoint == null)
                {
                    return(next(context));
                }

                IEnumerable <string> templates;
                IODataRoutingMetadata metadata = endpoint.Metadata.GetMetadata <IODataRoutingMetadata>();
                if (metadata != null)
                {
                    templates = metadata.Template.GetTemplates();
                }

                return(next(context));
            });

            app.UseAuthorization();

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllers();
            });
        }
Пример #12
0
        internal async Task HandleEndpointsAsync(HttpContext context)
        {
            if (context == null)
            {
                throw Error.ArgumentNull(nameof(context));
            }

            StringBuilder      nonSb      = new StringBuilder();
            StringBuilder      sb         = new StringBuilder();
            EndpointDataSource dataSource = context.RequestServices.GetRequiredService <EndpointDataSource>();

            foreach (var endpoint in dataSource.Endpoints)
            {
                ControllerActionDescriptor controllerActionDescriptor = endpoint.Metadata.GetMetadata <ControllerActionDescriptor>();
                if (controllerActionDescriptor == null)
                {
                    continue;
                }

                IODataRoutingMetadata metadata = endpoint.Metadata.GetMetadata <IODataRoutingMetadata>();
                if (metadata == null)
                {
                    AppendRoute(nonSb, endpoint);
                }
                else
                {
                    AppendRoute(sb, endpoint);
                }
            }

            string output = ODataRouteMappingHtmlTemplate.Replace("ODATACONTENT", sb.ToString(), StringComparison.Ordinal);

            output = output.Replace("NONENDPOINTCONTENT", nonSb.ToString(), StringComparison.Ordinal);

            context.Response.Headers["Content_Type"] = "text/html";
            await context.Response.WriteAsync(output).ConfigureAwait(false);
        }
        /// <summary>
        /// Applies the policy to the CandidateSet.
        /// </summary>
        /// <param name="httpContext">The context associated with the current request.</param>
        /// <param name="candidates">The CandidateSet.</param>
        /// <returns>The task.</returns>
        public Task ApplyAsync(HttpContext httpContext, CandidateSet candidates)
        {
            if (httpContext == null)
            {
                throw Error.ArgumentNull(nameof(httpContext));
            }

            IODataFeature odataFeature = httpContext.ODataFeature();

            if (odataFeature.Path != null)
            {
                // If we have the OData path setting, it means there's some Policy working.
                // Let's skip this default OData matcher policy.
                return(Task.CompletedTask);
            }

            // The goal of this method is to perform the final matching:
            // Map between route values matched by the template and the ones we want to expose to the action for binding.
            // (tweaking the route values is fine here)
            // Invalidating the candidate if the key/function values are not valid/missing.
            // Perform overload resolution for functions by looking at the candidates and their metadata.
            for (var i = 0; i < candidates.Count; i++)
            {
                ref CandidateState candidate = ref candidates[i];
                if (!candidates.IsValidCandidate(i))
                {
                    continue;
                }

                IODataRoutingMetadata metadata = candidate.Endpoint.Metadata.OfType <IODataRoutingMetadata>().FirstOrDefault();
                if (metadata == null)
                {
                    continue;
                }

                if (odataFeature.Path != null)
                {
                    // If it's odata endpoint, and we have a path set, let other odata endpoints invalid.
                    candidates.SetValidity(i, false);
                    continue;
                }

                ODataTemplateTranslateContext translatorContext =
                    new ODataTemplateTranslateContext(httpContext, candidate.Endpoint, candidate.Values, metadata.Model);

                ODataPath odataPath = _translator.Translate(metadata.Template, translatorContext);
                if (odataPath != null)
                {
                    odataFeature.RoutePrefix = metadata.Prefix;
                    odataFeature.Model       = metadata.Model;
                    odataFeature.Path        = odataPath;

                    MergeRouteValues(translatorContext.UpdatedValues, candidate.Values);

                    // Shall we break the remaining candidates?
                    // So far the answer is no. Because we can use this matcher to obsolete the unmatched endpoint.
                    // break;
                }
                else
                {
                    candidates.SetValidity(i, false);
                }
            }
Пример #14
0
        /// <summary>
        /// Handle ~/$odata request
        /// </summary>
        /// <param name="context">The http context.</param>
        /// <returns>The task.</returns>
        public static async Task HandleOData(HttpContext context)
        {
            EndpointDataSource dataSource = context.RequestServices.GetRequiredService <EndpointDataSource>();

            StringBuilder sb = new StringBuilder();

            foreach (var endpoint in dataSource.Endpoints)
            {
                IODataRoutingMetadata metadata = endpoint.Metadata.GetMetadata <IODataRoutingMetadata>();
                if (metadata == null)
                {
                    continue;
                }

                ControllerActionDescriptor controllerActionDescriptor = endpoint.Metadata.GetMetadata <ControllerActionDescriptor>();
                if (controllerActionDescriptor == null)
                {
                    continue;
                }

                // controller and action details
                StringBuilder action = new StringBuilder();
                if (controllerActionDescriptor.MethodInfo.ReturnType != null)
                {
                    action.Append(controllerActionDescriptor.MethodInfo.ReturnType.Name + " ");
                }
                else
                {
                    action.Append("void ");
                }
                action.Append(controllerActionDescriptor.MethodInfo.Name + "(");
                action.Append(string.Join(",", controllerActionDescriptor.MethodInfo.GetParameters().Select(p => p.ParameterType.Name)));
                action.Append(")");
                string actionName = controllerActionDescriptor.MethodInfo.Name;

                sb.Append("<tr>");
                sb.Append($"<td>{controllerActionDescriptor.ControllerTypeInfo.FullName}</td>");
                sb.Append($"<td>{action}</td>");

                // http methods
                string httpMethods = string.Join(",", metadata.HttpMethods);
                sb.Append($"<td>{httpMethods.ToUpper()}</td>");

                // OData routing templates
                RouteEndpoint routeEndpoint = endpoint as RouteEndpoint;
                if (routeEndpoint != null)
                {
                    sb.Append("<td>~/").Append(routeEndpoint.RoutePattern.RawText).Append("</td></tr>");
                }
                else
                {
                    int index = 1;
                    sb.Append("<td>");
                    foreach (var template in metadata.Template.GetTemplates())
                    {
                        sb.Append($"{index++})");
                        if (string.IsNullOrEmpty(metadata.Prefix))
                        {
                            sb.Append(" ~/");
                        }
                        else
                        {
                            sb.Append($" ~/{metadata.Prefix}/");
                        }

                        sb.Append(template).Append("<br/>");
                    }
                    sb.Append("</td></tr>");
                }
            }

            string output = ODataRouteMappingHtmlTemplate.Replace("{CONTNET}", sb.ToString());

            context.Response.Headers["Content_Type"] = "text/html";

            await context.Response.WriteAsync(output);

            //string content = sb.ToString();
            //byte[] requestBytes = Encoding.UTF8.GetBytes(content);
            //context.Response.Headers.ContentLength = requestBytes.Length;
            //context.Response.Body = new MemoryStream(requestBytes);
            //await Task.CompletedTask;
        }
Пример #15
0
        public Task ApplyAsync(HttpContext httpContext, CandidateSet candidates)
        {
            if (httpContext == null)
            {
                throw new ArgumentNullException(nameof(httpContext));
            }

            IODataFeature odataFeature = httpContext.ODataFeature();

            if (odataFeature.Path != null)
            {
                // If we have the OData path setting, it means there's some Policy working.
                // Let's skip this default OData matcher policy.
                return(Task.CompletedTask);
            }

            for (var i = 0; i < candidates.Count; i++)
            {
                ref CandidateState candidate = ref candidates[i];
                if (!candidates.IsValidCandidate(i))
                {
                    continue;
                }

                IODataRoutingMetadata metadata = candidate.Endpoint.Metadata.OfType <IODataRoutingMetadata>().FirstOrDefault();
                if (metadata == null)
                {
                    continue;
                }

                // Get api-version query from HttpRequest?
                QueryStringApiVersionReader reader = new QueryStringApiVersionReader("api-version");
                string apiVersionStr = reader.Read(httpContext.Request);
                if (apiVersionStr == null)
                {
                    candidates.SetValidity(i, false);
                    continue;
                }
                ApiVersion apiVersion = ApiVersion.Parse(apiVersionStr);

                IEdmModel model = GetEdmModel(apiVersion);
                if (model == null)
                {
                    candidates.SetValidity(i, false);
                    continue;
                }

                if (!IsApiVersionMatch(candidate.Endpoint.Metadata, apiVersion))
                {
                    candidates.SetValidity(i, false);
                    continue;
                }

                ODataTemplateTranslateContext translatorContext
                    = new ODataTemplateTranslateContext(httpContext, candidate.Endpoint, candidate.Values, model);

                try
                {
                    ODataPath odataPath = _translator.Translate(metadata.Template, translatorContext);
                    if (odataPath != null)
                    {
                        odataFeature.RoutePrefix = metadata.Prefix;
                        odataFeature.Model       = model;
                        odataFeature.Path        = odataPath;

                        ODataOptions options = new ODataOptions();
                        UpdateQuerySetting(options);
                        options.AddRouteComponents(model);
                        odataFeature.Services = options.GetRouteServices(string.Empty);

                        MergeRouteValues(translatorContext.UpdatedValues, candidate.Values);
                    }
                    else
                    {
                        candidates.SetValidity(i, false);
                    }
                }
                catch
                {
                    candidates.SetValidity(i, false);
                }
            }