vNext: Console app that uses razor views without h

2020-06-23 07:07发布

问题:

I am creating console application that does some file conversions. These conversions are easily done creating a model from the input file and then executing razor models for the output.

To have this working in the IDE I used Visual Studio 2015 preview and created a vnext console application that uses MVC. (You get razor support out of the box then). To get this all working you need to host the MVC app though, and the cheapest way to do that is hosting is through a WebListener. So I host the MVC app and then call it through "http://localhost:5003/etc/etc" to get the rendered views that construct the output.

But the console app is not supposed to listen to/use a port. It is just a command line tool for file conversions. If multiple instances would run at the same time they would fight to host the pages on the same port. (This could of coarse be prevented by choosing a port dynamically, but this is not what I am looking for)

So my question is how would you get this working without using a port, but using as much of the vnext frameworks as possible.

In short: how can I use cshtml files that I pass models in a console app that does not use a port using the vnext razor engine.

Here is some code I currently use:

Program.cs

using Microsoft.AspNet.Hosting;
using Microsoft.AspNet.Http;
using Microsoft.AspNet.Mvc;
using Microsoft.Framework.ConfigurationModel;
using Microsoft.Framework.DependencyInjection;
using Microsoft.Framework.DependencyInjection.Fallback;
using System;
using System.IO;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Threading;
using System.Threading.Tasks;
using System.Xml.Linq;

namespace ConsoleTest
{
    public class Program
    {
        private readonly IServiceProvider _hostServiceProvider;

        public Program(IServiceProvider hostServiceProvider)
        {
            _hostServiceProvider = hostServiceProvider;
        }

        public async Task<string> GetWebpageAsync()
        {
            using (var httpClient = new HttpClient())
            {
                httpClient.BaseAddress = new Uri("http://localhost:5003/home/svg?idx=1");
                httpClient.DefaultRequestHeaders.Accept.Clear();
                httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("text/xml"));
                return await httpClient.GetStringAsync("");
            }
        }

        public Task<int> Main(string[] args)
        {
            var config = new Configuration();
            config.AddCommandLine(args);

            var serviceCollection = new ServiceCollection();
            serviceCollection.Add(HostingServices.GetDefaultServices(config));
            serviceCollection.AddInstance<IHostingEnvironment>(new HostingEnvironment() { WebRoot = "wwwroot" });
            var services = serviceCollection.BuildServiceProvider(_hostServiceProvider);

            var context = new HostingContext()
            {
                Services = services,
                Configuration = config,
                ServerName = "Microsoft.AspNet.Server.WebListener",
                ApplicationName = "ConsoleTest"
            };

            var engine = services.GetService<IHostingEngine>();
            if (engine == null)
            {
                throw new Exception("TODO: IHostingEngine service not available exception");
            }

            using (engine.Start(context))
            {
                var tst = GetWebpageAsync();
                tst.Wait();
                File.WriteAllText(@"C:\\result.svg", tst.Result.TrimStart());

                Console.WriteLine("Started the server..");
                Console.WriteLine("Press any key to stop the server");
                Console.ReadLine();
            }
            return Task.FromResult(0);
        }
    }
}

Startup.cs

using Microsoft.AspNet.Builder;
using Microsoft.Framework.DependencyInjection;
using Microsoft.AspNet.Routing;
using Microsoft.Framework.ConfigurationModel;

namespace ConsoleTest
{
    public class Startup
    {
        public IConfiguration Configuration { get; private set; }

        public void ConfigureServices(IServiceCollection services)
        {
            // Add MVC services to the services container
            services.AddMvc();
        }

        public void Configure(IApplicationBuilder app)
        {
            //Configure WebFx
            app.UseMvc(routes =>
            {
                routes.MapRoute(
                    null,
                    "{controller}/{action}",
                    new { controller = "Home", action = "Index" });
            });
        }
    }
}

回答1:

I solved it using the following code:

Program.cs

using System;
using System.Threading.Tasks;
using Microsoft.AspNet.TestHost;
using Microsoft.AspNet.Builder;
using Microsoft.Framework.Runtime.Infrastructure;

namespace ConsoleTest
{
    public class Program
    {
        private Action<IApplicationBuilder> _app;
        private IServiceProvider _services;

        public async Task<string> TestMe()
        {
            var server = TestServer.Create(_services, _app);
            var client = server.CreateClient();
            return await client.GetStringAsync("http://localhost/home/svg?idx=1");
        }

        public void Main(string[] args)
        {
            _services = CallContextServiceLocator.Locator.ServiceProvider;
            _app = new Startup().Configure;

            var x = TestMe();
            x.Wait();
            Console.WriteLine(x.Result);

            Console.ReadLine();
        }
    }
}

Startup.cs

using Microsoft.AspNet.Builder;
using Microsoft.Framework.DependencyInjection;
using Microsoft.AspNet.Routing;

namespace ConsoleTest
{
    public class Startup
    {
        public void Configure(IApplicationBuilder app)
        {
            app.UseServices(services =>
            {
                // Add MVC services to the services container
                services.AddMvc();
            });
            //Configure WebFx
            app.UseMvc(routes =>
            {
                routes.MapRoute(
                    null,
                    "{controller}/{action}",
                    new { controller = "Home", action = "Index" });
            });
        }
    }
}