Ejemplo n.º 1
0
        public HttpControllerDescriptor SelectController(HttpRequestMessage request)
        {
            // Log this lookup and add to history for insights
            var log = new Log("Sxc.Http", null, request?.RequestUri?.AbsoluteUri);

            AddToInsightsHistory(request?.RequestUri?.AbsoluteUri, log);

            var wrapLog = log.Call <HttpControllerDescriptor>();

            if (!HandleRequestWithThisController(request))
            {
                return(wrapLog("upstream", PreviousSelector.SelectController(request)));
            }

            var routeData = request.GetRouteData();

            var controllerTypeName = routeData.Values[Names.Controller] + "Controller";

            // Now Handle the 2sxc app-api queries

            // Figure out the Path, or show error for that
            var appFolder = AppFolderUtilities.GetAppFolder(request, log, wrapLog);

            var controllerPath = "";

            try
            {
                // new for 2sxc 9.34 #1651
                var edition = "";
                if (routeData.Values.ContainsKey(Names.Edition))
                {
                    edition = routeData.Values[Names.Edition].ToString();
                }
                if (!string.IsNullOrEmpty(edition))
                {
                    edition += "/";
                }

                log.Add($"Edition: {edition}");

                var tenant           = Eav.Factory.StaticBuild <DnnSite>();
                var controllerFolder = Path.Combine(tenant.AppsRootRelative, appFolder, edition + "api/");

                controllerFolder = controllerFolder.Replace("\\", @"/");
                log.Add($"Controller Folder: {controllerFolder}");

                controllerPath = Path.Combine(controllerFolder + controllerTypeName + ".cs");
                log.Add($"Controller Path: {controllerPath}");

                // note: this may look like something you could optimize/cache the result, but that's a bad idea
                // because when the file changes, the type-object will be different, so please don't optimize :)
                if (File.Exists(HostingEnvironment.MapPath(controllerPath)))
                {
                    var assembly = BuildManager.GetCompiledAssembly(controllerPath);
                    var type     = assembly.GetType(controllerTypeName, true, true);

                    // help with path resolution for compilers running inside the created controller
                    request?.Properties.Add(CodeCompiler.SharedCodeRootPathKeyInCache, controllerFolder);

                    var descriptor = new HttpControllerDescriptor(_config, type.Name, type);
                    return(wrapLog("ok", descriptor));
                }

                log.Add("path not found, error will be thrown in a moment");
            }
            catch (Exception e)
            {
                var msg = ApiErrPrefix + ApiErrGeneral + ApiErrSuffix;
                throw AppFolderUtilities.ReportToLogAndThrow(request, HttpStatusCode.InternalServerError, e, msg, wrapLog);
            }

            var msgFinal = $"2sxc Api Controller Finder: Controller {controllerTypeName} not found in app. " +
                           $"We checked the virtual path '{controllerPath}'";

            throw AppFolderUtilities.ReportToLogAndThrow(request, HttpStatusCode.NotFound, new Exception(), msgFinal, wrapLog);
        }
Ejemplo n.º 2
0
        public HttpResponseMessage Inspect(string path)
        {
            var wrapLog = Log.Call <HttpResponseMessage>();

            Log.Add($"Controller Path from appRoot: {path}");

            if (string.IsNullOrWhiteSpace(path) || path.Contains(".."))
            {
                var msg = $"Error: bad parameter {path}";
                return(wrapLog(msg, Request.CreateErrorResponse(HttpStatusCode.InternalServerError, msg)));
            }

            // Ensure make windows path slashes to make later work easier
            path = path.Backslash();

            try
            {
                var controllerVirtualPath = Path.Combine(AppFolderUtilities.GetAppFolderVirtualPath(Request, Log), path);
                Log.Add($"Controller Virtual Path: {controllerVirtualPath}");

                if (!File.Exists(HostingEnvironment.MapPath(controllerVirtualPath)))
                {
                    var msg = $"Error: can't find controller file: {controllerVirtualPath}";
                    return(wrapLog(msg, Request.CreateErrorResponse(HttpStatusCode.InternalServerError, msg)));
                }

                var assembly = BuildManager.GetCompiledAssembly(controllerVirtualPath);

                var controllerName = path.Substring(path.LastIndexOf('\\') + 1);
                controllerName = controllerName.Substring(0, controllerName.IndexOf('.'));
                var controller = assembly.DefinedTypes.FirstOrDefault(a => controllerName.Equals(a.Name, StringComparison.InvariantCultureIgnoreCase));
                if (controller == null)
                {
                    var msg = $"Error: can't find controller class: {controllerName} in file {Path.GetFileNameWithoutExtension(path)}. This can happen if the controller class does not have the same name as the file.";
                    return(wrapLog(msg, Request.CreateErrorResponse(HttpStatusCode.InternalServerError, msg)));
                }

                var controllerSecurity = GetSecurity(controller);
                var controllerDto      = new ApiControllerDto
                {
                    controller = controller.Name,
                    actions    = controller.GetMethods()
                                 .Where(methodInfo => methodInfo.IsPublic &&
                                        !methodInfo.IsSpecialName &&
                                        GetHttpVerbs(methodInfo).Count > 0)
                                 .Select(methodInfo =>
                    {
                        var methodSecurity = GetSecurity(methodInfo);
                        var mergedSecurity = MergeSecurity(controllerSecurity, methodSecurity);
                        return(new ApiActionDto
                        {
                            name = methodInfo.Name,
                            verbs = GetHttpVerbs(methodInfo).Select(m => m.ToUpperInvariant()),
                            parameters = methodInfo.GetParameters().Select(p => new ApiActionParamDto
                            {
                                name = p.Name,
                                type = ApiExplorerJs.JsTypeName(p.ParameterType),
                                defaultValue = p.DefaultValue,
                                isOptional = p.IsOptional,
                                isBody = IsBody(p),
                            }).ToArray(),
                            security = methodSecurity,
                            mergedSecurity = mergedSecurity,
                            returns = ApiExplorerJs.JsTypeName(methodInfo.ReturnType),
                        });
                    }),
                    security = controllerSecurity
                };

                var responseMessage = Request.CreateResponse(HttpStatusCode.OK);
                responseMessage.Content = new StringContent(controllerDto.ToJson(), Encoding.UTF8, "application/json");
                return(wrapLog("ok", responseMessage));
            }
            catch (Exception exc)
            {
                return(wrapLog($"Error: {exc.Message}.", Request.CreateErrorResponse(HttpStatusCode.InternalServerError, exc)));
            }
        }