HelloWorldComponent和System.Func`2之间没有可用的转换[System.Collections.Generic.IDictionary`2 //参数名称:签名

时间:2015-04-22 16:31:31

标签: owin katana owin-middleware

我正在研究Scott Allen关于Pluralsight的MVC 5基础课程

我在"使用(WebApp.Start(uri))"在下面的代码中。

错误是

An unhandled exception of type 'System.ArgumentException' occurred in Microsoft.Owin.dll
  System.ArgumentException was unhandled
  HResult=-2147024809
  Message=No conversion available between ConsoleApplication1.HelloWorldComponent and System.Func`2[System.Collections.Generic.IDictionary`2[System.String,System.Object],System.Threading.Tasks.Task].
Parameter name: signature
  Source=Microsoft.Owin
  ParamName=signature
  StackTrace:
       at Microsoft.Owin.Builder.AppBuilder.Convert(Type signature, Object app)
       at Microsoft.Owin.Builder.AppBuilder.BuildInternal(Type signature)
       at Microsoft.Owin.Builder.AppBuilder.Build(Type returnType)
       at Microsoft.Owin.Hosting.ServerFactory.ServerFactoryAdapter.Create(IAppBuilder builder)
       at Microsoft.Owin.Hosting.Engine.HostingEngine.StartServer(StartContext context)
       at Microsoft.Owin.Hosting.Engine.HostingEngine.Start(StartContext context)
       at Microsoft.Owin.Hosting.Starter.DirectHostingStarter.Start(StartOptions options)
       at Microsoft.Owin.Hosting.Starter.HostingStarter.Start(StartOptions options)
       at Microsoft.Owin.Hosting.WebApp.StartImplementation(IServiceProvider services, StartOptions options)
       at Microsoft.Owin.Hosting.WebApp.Start(StartOptions options)
       at Microsoft.Owin.Hosting.WebApp.Start[TStartup](StartOptions options)
       at Microsoft.Owin.Hosting.WebApp.Start[TStartup](String url)
       at ConsoleApplication1.Program.Main(String[] args) in e:\EShared\Dev2015\WebAppScottAllen\ConsoleApplication1\ConsoleApplication1\Program.cs:line 16
       at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args)
       at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
       at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
       at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
       at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
       at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
       at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
       at System.Threading.ThreadHelper.ThreadStart()
  InnerException: 

代码是

using System;
using System.Collections.Generic;
using System.IO;
using System.Threading.Tasks;
using Microsoft.Owin.Hosting;
using Owin;
namespace ConsoleApplication1
{
    using AppFunc = Func<IDictionary<string, object>, Task>;
    class Program
    {
        static void Main(string[] args)
        {
            string uri = "http://localhost:8080";
            using (WebApp.Start<Startup>(uri))   // Katana Please start, using the configuration from the Startup class and listening on the port given by the uri
            {
                Console.WriteLine("Started!");
                Console.ReadKey();
                Console.WriteLine("Stopping!");
            }
        }
    }

    public class Startup
    {
        public void Configuration(IAppBuilder app)
        {
            app.Use<HelloWorldComponent>();
        }
    }

    public class HelloWorldComponent
    {
        AppFunc _next;
        public HelloWorldComponent(AppFunc next)
        {
            _next = next;
        }

        // Katana uses reflection to find this Invoke function that matches the AppFunc signature
        public Task Invoke(IDictionary<string, object> environment)
        { 
            var response = environment["owin.ResponseBody"] as Stream;

            using (var writer = new StreamWriter(response))
            {
                return writer.WriteAsync("Hello");
            }
        }
    }
}

packages.config是

<?xml version="1.0" encoding="utf-8"?>
<packages>
  <package id="Microsoft.Owin" version="3.0.1" targetFramework="net451" />
  <package id="Microsoft.Owin.Diagnostics" version="3.0.1" targetFramework="net451" />
  <package id="Microsoft.Owin.Host.HttpListener" version="3.0.1" targetFramework="net451" />
  <package id="Microsoft.Owin.Host.SystemWeb" version="3.0.1" targetFramework="net451" />
  <package id="Microsoft.Owin.Hosting" version="3.0.1" targetFramework="net451" />
  <package id="Owin" version="1.0" targetFramework="net451" />
</packages>

我想知道没有使用这个消息,所以我想知道什么可以改变

2 个答案:

答案 0 :(得分:3)

有一种编写中间件组件的新方法,如下所示:

public class HelloWorldComponent : OwinMiddleware
{
    public HelloWorldComponent(OwinMiddleware next) : base(next) { }

    public override Task Invoke(IOwinContext context)
    {
        return context.Response.WriteAsync("Hello, World!");
    }
}

具体来说,构造函数必须接受OwinMiddleware引用作为其第一个参数,否则会出现错误,因为ctor签名与当前Owin实现的预期不匹配。< / p>

此外,请考虑以下参数化用法

    var param1 = "Hello, World!";
    appBuilder.Use<HelloWorldComponent>(param1)

要正确支持这一点,您需要一个修改过的构造函数签名:

public class HelloWorldComponent : OwinMiddleware
{
    public HelloWorldComponent(OwinMiddleware next) : base(next) { }

    public override Task Invoke(IOwinContext context, string param1)
    {
        return context.Response.WriteAsync(param1);
    }
}

因此,允许我们通过Use()的params数组来参数化我们的中间件。

答案 1 :(得分:0)

继承OwinMiddleware会限制你对OWIN的Katana实施。
从传递的OwinContext创建environment应该适合您

class HelloWorldComponent 
    {
        private readonly AppFunc _next;

        public HelloWorldComponent (AppFunc next)
        {
            _next = next;
        }

        public async Task Invoke(IDictionary<string, object> environment)
        {

            var ctx = new OwinContext(environment);
            await ctx.Response.WriteAsync("Hello World");
            await _next(environment);
        }
    }