Не удается получить динамическую HTML-страницу, используя автономный AspNetCore MVC внутри консольного приложения в качестве службы Windows

#asp.net #asp.net-mvc #asp.net-mvc-5 #asp.net-core #self-hosting

#asp.net #asp.net-mvc #asp.net-mvc-5 #asp.net-core #самостоятельный хостинг

Вопрос:

Проблема: необходимо иметь возможность устанавливать и запускать Asp.Net Приложение MVC (которое возвращает приложение SPA angular) как служба Windows

Тема: я использую ASp.Net Ядро MVC внутри консольного приложения и запустите его как службу Windows, и оно работает отлично (все запросы попадают в нужное место), но return View(); возвращает пустую страницу вместо правильного html.

  public class Startup
{
    public IContainer ApplicationContainer { get; private set; }
    public IConfigurationRoot Configuration { get; private set; }

    public Startup(IHostingEnvironment env)
    {
        var builder = new ConfigurationBuilder()
            .SetBasePath(env.ContentRootPath)
            .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
            .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true)
            .AddEnvironmentVariables();

        if (env.IsDevelopment())
        {
            // This will push telemetry data through Application Insights pipeline faster, allowing you to view results immediately.
            builder.AddApplicationInsightsSettings(developerMode: true);
        }
        Configuration = builder.Build();

    }

    // This method gets called by the runtime. Use this method to add services to the container.
    public IServiceProvider ConfigureServices(IServiceCollection services)
    {
        // Add framework services.
        services.AddApplicationInsightsTelemetry(Configuration);
        services.AddMvc().AddWebApiConventions();

        services.AddCors();

        services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();

        var builder = new ContainerBuilder();
        builder.Populate(services);

        this.ApplicationContainer = builder.Build();
        return new AutofacServiceProvider(this.ApplicationContainer);
    }

    // This method gets called at the runtime. Use this method to configure the HTTP request pipeline.
    public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
    {
        app.UseApplicationInsightsRequestTelemetry();
        app.UseApplicationInsightsExceptionTelemetry();

        var listener = app.ServerFeatures.Get<WebListener>();
        if (listener != null)
        {
            listener.AuthenticationManager.AuthenticationSchemes =
            AuthenticationSchemes.NTLM;
        }

        app.UseFileServer();
        app.UseCors(builder => builder.AllowAnyOrigin());

        app.UseMvc(routes =>
        {
            routes.MapRoute(
                name: "default",
                template: "{controller=Home}/{action=Index}/{id?}");
            routes.MapWebApiRoute(
                name: "defaultApi",
                template: "api/{controller}/{action}/{id?}");
        });
    }
}

public class Program
{
    public static string ServiceName = "WebApp";

    static void Main(string[] args)
    {
        try
        {
            var exePath = Process.GetCurrentProcess().MainModule.FileName;
    //sure it's not necessary! It was just a try 
directoryPath = directoryPath.Replace("\bin", "");
            var directoryPath = Path.GetDirectoryName(exePath);
            var httpAddress = "https://localhost";
            var httpPort = "10778";
            var host = new WebHostBuilder()
                .UseWebListener()
                .UseWebRoot(directoryPath   "\wwwroot") //also just a try to navigate it right
                .UseContentRoot(directoryPath)
                .UseUrls($"{httpAddress}:{httpPort}")
                .UseStartup<Startup>()
                .Build();

            if (Debugger.IsAttached || args.Contains("--debug"))
            {
                host.Run();
            }
            else
            {
                host.RunAsService();
            }
        }
        catch (Exception ex)
        {
            var exMessage = ex.Message;
        }
    }
}
  

Пример проекта можно загрузить здесь

Обновить:

После включения app.UseDeveloperExceptionPage(); в метод Configure получите такой список ошибок

введите описание изображения здесь

Комментарии:

1. Я получаю Could not load file or assembly 'Microsoft.AspNetCore.Routing, Version=1.0.0.0 сообщение об ошибке при попытке запустить ваш код. Собираюсь разобраться в этом.

2. после восстановления всех пакетов nuget проект должен работать нормально, но вы также можете загрузить их из этого источника

3. Можете ли вы включить свой файл App.config в исходный код?

4. конечно! я обновил исходный код

5. Похоже, мне нужно включить все ссылки, которые я добавил с помощью nuget, в файл app.config. может быть, вы знаете, как это сделать автоматически?

Ответ №1:

Создайте новый таргетинг на веб-приложение .NET Core.NET v4.6.1. Смотрите Скриншот ниже.

введите описание изображения здесь

Таким образом, вы получите exe веб-приложение по умолчанию, и оно предназначено для .NET версии 4.6.1.

Комментарии:

1. Интересный материал !!, но, к сожалению, я должен использовать .net 4.6.1.

2. Можете ли вы тогда уточнить свой вопрос? Вам нужно консольное приложение или служба Windows? Ваш текущий код показывает, что вы создаете консольное приложение. Если вы нацелены на .net 4.6.1, вам нужен .net core MVC или достаточно стандартного .net MVC?

3. ОК. У меня есть автономный веб-api, который работает со средой Windows и доступен по запросам из браузера. Теперь мне нужно сохранить все это поведение (и я делаю это действительно хорошо с текущей примерной реализацией) и добавить к этому SPA на основе angular, чтобы иметь возможность настраивать это поведение службы web api. Это объяснение понятно или вам может понадобиться дополнительная информация?

4. Спасибо за разъяснение. Я думаю, что это на самом деле проще, чем я думал! Просто обновил мой ответ. Дайте мне знать, если у вас есть какие-либо другие вопросы.

5. Спасибо за предложение! В целом это достаточно хорошо, но если все немного сложнее, это вызывает некоторые досадные проблемы, поэтому я решил использовать другой архитектурный подход для решения моей проблемы. в любом случае спасибо!