PrepareResponse()。AsActionResult()抛出不支持的异常DotNetOpenAuth CTP

时间:2011-12-13 22:33:38

标签: asp.net-mvc-3 dotnetopenauth oauth-2.0

目前我正在使用DotNetOpenAuth CTP版本开发OAuth2授权服务器。我的授权服务器在asp.net MVC3中,它基于库提供的示例。一切正常,直到应用程序达到用户授权消费者客户端的程度。

我的OAuth控制器内部有一个操作,它负责授权过程,与示例中的等效操作非常相似:

[Authorize, HttpPost, ValidateAntiForgeryToken]
    public ActionResult AuthorizeResponse(bool isApproved)
    {
        var pendingRequest = this.authorizationServer.ReadAuthorizationRequest();

        if (pendingRequest == null)
        {
            throw new HttpException((int)HttpStatusCode.BadRequest, "Missing authorization request.");
        }

        IDirectedProtocolMessage response;
        if (isApproved)
        {
            var client = MvcApplication.DataContext.Clients.First(c => c.ClientIdentifier == pendingRequest.ClientIdentifier);
            client.ClientAuthorizations.Add(
                new ClientAuthorization
                {
                    Scope = OAuthUtilities.JoinScopes(pendingRequest.Scope),
                    User = MvcApplication.LoggedInUser,
                    CreatedOn = DateTime.UtcNow,
                });
            MvcApplication.DataContext.SaveChanges();
            response = this.authorizationServer.PrepareApproveAuthorizationRequest(pendingRequest, User.Identity.Name);
        }
        else
        {
            response = this.authorizationServer.PrepareRejectAuthorizationRequest(pendingRequest);
        }

        return this.authorizationServer.Channel.PrepareResponse(response).AsActionResult();
    }

每次程序到达此行:

this.authorizationServer.Channel.PrepareResponse(response).AsActionResult();

系统抛出一个异常,我研究过但没有成功。例外情况如下: LINQ to Entities中仅支持无参数构造函数和初始值设定项。

堆栈跟踪:http://pastebin.com/TibCax2t

我与样本做的唯一不同的是我使用了实体框架的代码第一种方法,我认为样本是使用自动生成实体的设计器完成的。

提前谢谢。

2 个答案:

答案 0 :(得分:5)

如果你从这个例子开始,安德鲁所讨论的问题就在DatabaseKeyNonceStore.cs。这两种方法都有一个例外:

    public CryptoKey GetKey(string bucket, string handle) {
        // It is critical that this lookup be case-sensitive, which can only be configured at the database.
        var matches = from key in MvcApplication.DataContext.SymmetricCryptoKeys
                      where key.Bucket == bucket && key.Handle == handle
                      select new CryptoKey(key.Secret, key.ExpiresUtc.AsUtc());

        return matches.FirstOrDefault();
    }

    public IEnumerable<KeyValuePair<string, CryptoKey>> GetKeys(string bucket) {
        return from key in MvcApplication.DataContext.SymmetricCryptoKeys
               where key.Bucket == bucket
               orderby key.ExpiresUtc descending
               select new KeyValuePair<string, CryptoKey>(key.Handle, new CryptoKey(key.Secret, key.ExpiresUtc.AsUtc()));
    }

我已经解决了在查询之外移动初始化的问题:

    public CryptoKey GetKey(string bucket, string handle) {
        // It is critical that this lookup be case-sensitive, which can only be configured at the database.
        var matches = from key in db.SymmetricCryptoKeys
                      where key.Bucket == bucket && key.Handle == handle
                      select key;

        var match = matches.FirstOrDefault();

        CryptoKey ck = new CryptoKey(match.Secret, match.ExpiresUtc.AsUtc());

        return ck;
    }

    public IEnumerable<KeyValuePair<string, CryptoKey>> GetKeys(string bucket) {
        var matches = from key in db.SymmetricCryptoKeys
               where key.Bucket == bucket
               orderby key.ExpiresUtc descending
               select key;

        List<KeyValuePair<string, CryptoKey>> en = new List<KeyValuePair<string, CryptoKey>>();

        foreach (var key in matches)
            en.Add(new KeyValuePair<string, CryptoKey>(key.Handle, new CryptoKey(key.Secret, key.ExpiresUtc.AsUtc())));

        return en.AsEnumerable<KeyValuePair<string,CryptoKey>>();
    }

我不确定这是最好的方法,但它确实有效!

答案 1 :(得分:1)

看起来您的ICryptoKeyStore实现可能正在尝试直接存储CryptoKey,但它不是与Entity框架兼容的类(由于没有公共默认构造函数)。相反,定义您自己的实体类以便在CryptoKey中存储数据,并且您的ICryptoKeyStore负责在两种数据类型之间进行转换以进行持久性和检索。