Copied to clipboard

Flag this post as spam?

This post will be reported to the moderators as potential spam to be looked at


  • Laura 4 posts 24 karma points
    Dec 22, 2023 @ 19:16
    Laura
    0

    I want to make a backoffice API (I am programming a plugin) but the url for my controller doesn't work. I have tried so many but it always said: "Request error: The URL returned a 404 (not found)"

    I am using the umbraco version 13.0.1

    namespace UmbracoProject.App_Plugins.MyPluginName.backoffice.Controllers
    {
    [Umbraco.Web.Mvc.PluginController("ContentApi")]
    public class ContentController : UmbracoAuthorizedJsonController
    {
        public IEnumerable<string> PageNames()
        {
            return new[] { "Table", "Chair", "Desk", "Computer" };
        }
    }
    

    in my controllerName.controller.js

    $http.get("/umbraco/backoffice/ContentApi/Content/PageNames").then(function (response) {
    $scope.content.pages = response.data;
    }
    

    It would be really great if someone knew what the problem is, thank you!

  • John Sharp 20 posts 110 karma points
    Jan 01, 2024 @ 19:13
    John Sharp
    0

    Hi Laura,

    I've been doing something similar today

    [PluginController("Spero")]
    //[Route("umbraco/backoffice/api/[controller]/[action]")]
    public class ProductDataController : UmbracoAuthorizedApiController
    {
        private readonly IProductService _productService;
    
        public ProductDataController(IProductService productService)
        {
            this._productService = productService;
        }
    
    ...etc
    

    Without any further modifications, this URL works: https://localhost/umbraco/backoffice/Spero/ProductData/get

    I've left a commented line in, [Route... - if you uncomment it then it overrides everything and uses that URL and you'd have the API accessible at umbraco/backoffice/api/ProductData/get

    To answer your actual question, given the configuration you've specified above then this should work umbraco/backoffice/ContentApi/Content/PageNames - as it's what you're trying already it doesn't work, I'd try the [Route] attribute option.

    Also, is the controller in the main web application or in a separate library?

  • Laura 4 posts 24 karma points
    Jan 01, 2024 @ 20:58
    Laura
    0

    Hi John,

    thanks for your answer. I really don't know what I am doing differently... My Controller is in here: "\App_Plugins\PluginName\backoffice". However, it can't find "umbraco/backoffice/api/Content/PageNames" when I use [Route("umbraco/backoffice/api/[controller]/[action]")].

    Is there something else that I should configure?

  • John Sharp 20 posts 110 karma points
    Jan 01, 2024 @ 21:25
    John Sharp
    0

    OK.... so, on your method that you're trying to call, put [Route("{id"})].

    It should mean that you can call https://localhost/1

    Does that work, if not then you may need to look at the way program.cs is registering Controllers.

    I assume all othe APIs work?

  • Laura 4 posts 24 karma points
    Jan 01, 2024 @ 21:39
    Laura
    0

    Okay, then I believe the issue lies in the program.cs file

    Actually thats my first API and I don't know Umbraco very well.

    What should I configure in the program.cs file that it works?

  • John Sharp 20 posts 110 karma points
    Jan 01, 2024 @ 21:51
    John Sharp
    0

    OK, what happens if you remove the attribute completely?

    Also, what does your program.slcs look like?

  • Laura 4 posts 24 karma points
    Jan 02, 2024 @ 14:46
    Laura
    0

    Program.cs:

    public class Program
    {
    public static void Main(string[] args)
        => CreateHostBuilder(args)
            .Build()
            .Run();
    
    public static IHostBuilder CreateHostBuilder(string[] args) =>
        Host.CreateDefaultBuilder(args)
            .ConfigureUmbracoDefaults()
            .ConfigureWebHostDefaults(webBuilder =>
            {
                webBuilder.UseStaticWebAssets();
                webBuilder.UseStartup<Startup>();
            });
    }
    

    Startup.cs:

    public class Startup
    {
        private readonly IWebHostEnvironment _env;
        private readonly IConfiguration _config;
    
        /// <summary>
        /// Initializes a new instance of the <see cref="Startup" /> class.
        /// </summary>
        /// <param name="webHostEnvironment">The web hosting environment.</param>
        /// <param name="config">The configuration.</param>
        /// <remarks>
        /// Only a few services are possible to be injected here https://github.com/dotnet/aspnetcore/issues/9337.
        /// </remarks>
        public Startup(IWebHostEnvironment webHostEnvironment, IConfiguration config)
        {
            _env = webHostEnvironment ?? throw new ArgumentNullException(nameof(webHostEnvironment));
            _config = config ?? throw new ArgumentNullException(nameof(config));
        }
    
        /// <summary>
        /// Configures the services.
        /// </summary>
        /// <param name="services">The services.</param>
        /// <remarks>
        /// This method gets called by the runtime. Use this method to add services to the container.
        /// For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940.
        /// </remarks>
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddUmbraco(_env, _config)
                .AddBackOffice()
                .AddWebsite()
                .AddDeliveryApi()
                .AddComposers()
                .Build();
            services.AddControllers();
        }
    
        /// <summary>
        /// Configures the application.
        /// </summary>
        /// <param name="app">The application builder.</param>
        /// <param name="env">The web hosting environment.</param>
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
    
            app.UseUmbraco()
                .WithMiddleware(u =>
                {
                    u.UseBackOffice();
                    u.UseWebsite();
                })
                .WithEndpoints(u =>
                {
                    u.UseInstallerEndpoints();
                    u.UseBackOfficeEndpoints();
                    u.UseWebsiteEndpoints();
                });
        }
    }
    

    Thanks for your help!

  • John Sharp 20 posts 110 karma points
    Jan 02, 2024 @ 16:46
    John Sharp
    0

    That all looks sensible based what I understand. I've done some digging and found this bit of code that might help. Add it at the very end of the Configure method. It'll add a list of the defined endpoints into your Debug window.

    var sys = app.Services.GetRequiredService<IActionDescriptorCollectionProvider>();
    
    foreach (var item in sys.ActionDescriptors.Items)
    {
        if (item.AttributeRouteInfo is not null)
        {
            Debug.WriteLine($"{item.Id,38}. {item.DisplayName}");
            var ari = item.AttributeRouteInfo;
            Debug.WriteLine($"{ari.Template}");
        }
    }
    

    You'll get things like this from Umbraco itself, umbraco/delivery/api/v{version:apiVersion}/media/item/{path}*

    You should also see your stuff. For my project I got things like this umbraco/backoffice/api/Spero/Product/{id}

    If you don't see any of your APIs listed then you may need to investigate the MapRoute method https://learn.microsoft.com/en-us/aspnet/mvc/overview/older-versions-1/controllers-and-routing/creating-custom-routes-cs

            routes.MapRoute(
                "Blog",                                           // Route name
                "Archive/{entryDate}",                            // URL with parameters
                new { controller = "Archive", action = "Entry" }  // Parameter defaults
            );
    
Please Sign in or register to post replies

Write your reply to:

Draft