简体   繁体   English

System.Web.Http.Owin WebApi2安装失败

[英]System.Web.Http.Owin WebApi2 installation woes

One of the annoying things I have found with .net and NUGet is that I never know what version of anything is installed by default. 我在.net和NUGet中发现的一件烦人的事是,我永远不知道默认情况下会安装什么版本。 This can be really frustrating when trying to add things to an existing project..... 尝试在现有项目中添加内容时,这可能真的令人沮丧。

Here is my current dilemma. 这是我目前的困境。

I have an MVC 5 project with only MVC on it. 我有一个MVC 5项目,上面只有MVC。 This project is massive and the work to move it to another project would take too much time. 该项目规模巨大,将其移至另一个项目的工作将花费太多时间。 So, I opened up NUGet and type WebApi and installed the one that came along. 因此,我打开NUGet并键入WebApi并安装了随之而来的版本。

Then I created a blank WebApi project with Individual Accounts set up and copied the StartUp code into my current StartUp along with any other configuration that is needed. 然后,我创建了一个空白的WebApi项目,其中设置了“个人帐户”,并将“启动代码”以及所需的任何其他配置复制到了当前的“启动”中。

Then I came to create my AccountController which is just copied straight from the clean project I created. 然后,我开始创建我的AccountController,它直接从我创建的干净项目中直接复制而来。 It looks like this: 看起来像这样:

[Authorize]
[RoutePrefix("api/Account")]
public class AccountController : ApiController
{
    private const string LocalLoginProvider = "Local";

    public AccountController()
        : this(Startup.UserManagerFactory(), Startup.OAuthOptions.AccessTokenFormat)
    {
    }

    public AccountController(UserManager<IdentityUser> userManager,
        ISecureDataFormat<AuthenticationTicket> accessTokenFormat)
    {
        UserManager = userManager;
        AccessTokenFormat = accessTokenFormat;
    }

    public UserManager<IdentityUser> UserManager { get; private set; }
    public ISecureDataFormat<AuthenticationTicket> AccessTokenFormat { get; private set; }

    // GET api/Account/UserInfo
    [HostAuthentication(DefaultAuthenticationTypes.ExternalBearer)]
    [Route("UserInfo")]
    public UserInfoViewModel GetUserInfo()
    {
        ExternalLoginData externalLogin = ExternalLoginData.FromIdentity(User.Identity as ClaimsIdentity);

        return new UserInfoViewModel
        {
            UserName = User.Identity.GetUserName(),
            HasRegistered = externalLogin == null,
            LoginProvider = externalLogin != null ? externalLogin.LoginProvider : null
        };
    }

    // POST api/Account/Logout
    [Route("Logout")]
    public IHttpActionResult Logout()
    {
        Authentication.SignOut(CookieAuthenticationDefaults.AuthenticationType);
        return Ok();
    }

    // GET api/Account/ManageInfo?returnUrl=%2F&generateState=true
    [Route("ManageInfo")]
    public async Task<ManageInfoViewModel> GetManageInfo(string returnUrl, bool generateState = false)
    {
        IdentityUser user = await UserManager.FindByIdAsync(User.Identity.GetUserId());

        if (user == null)
        {
            return null;
        }

        List<UserLoginInfoViewModel> logins = new List<UserLoginInfoViewModel>();

        foreach (IdentityUserLogin linkedAccount in user.Logins)
        {
            logins.Add(new UserLoginInfoViewModel
            {
                LoginProvider = linkedAccount.LoginProvider,
                ProviderKey = linkedAccount.ProviderKey
            });
        }

        if (user.PasswordHash != null)
        {
            logins.Add(new UserLoginInfoViewModel
            {
                LoginProvider = LocalLoginProvider,
                ProviderKey = user.UserName,
            });
        }

        return new ManageInfoViewModel
        {
            LocalLoginProvider = LocalLoginProvider,
            UserName = user.UserName,
            Logins = logins,
            ExternalLoginProviders = GetExternalLogins(returnUrl, generateState)
        };
    }

    // POST api/Account/ChangePassword
    [Route("ChangePassword")]
    public async Task<IHttpActionResult> ChangePassword(ChangePasswordBindingModel model)
    {
        if (!ModelState.IsValid)
        {
            return BadRequest(ModelState);
        }

        IdentityResult result = await UserManager.ChangePasswordAsync(User.Identity.GetUserId(), model.OldPassword,
            model.NewPassword);
        IHttpActionResult errorResult = GetErrorResult(result);

        if (errorResult != null)
        {
            return errorResult;
        }

        return Ok();
    }

    // POST api/Account/SetPassword
    [Route("SetPassword")]
    public async Task<IHttpActionResult> SetPassword(SetPasswordBindingModel model)
    {
        if (!ModelState.IsValid)
        {
            return BadRequest(ModelState);
        }

        IdentityResult result = await UserManager.AddPasswordAsync(User.Identity.GetUserId(), model.NewPassword);
        IHttpActionResult errorResult = GetErrorResult(result);

        if (errorResult != null)
        {
            return errorResult;
        }

        return Ok();
    }

    // POST api/Account/AddExternalLogin
    [Route("AddExternalLogin")]
    public async Task<IHttpActionResult> AddExternalLogin(AddExternalLoginBindingModel model)
    {
        if (!ModelState.IsValid)
        {
            return BadRequest(ModelState);
        }

        Authentication.SignOut(DefaultAuthenticationTypes.ExternalCookie);

        AuthenticationTicket ticket = AccessTokenFormat.Unprotect(model.ExternalAccessToken);

        if (ticket == null || ticket.Identity == null || (ticket.Properties != null
            && ticket.Properties.ExpiresUtc.HasValue
            && ticket.Properties.ExpiresUtc.Value < DateTimeOffset.UtcNow))
        {
            return BadRequest("External login failure.");
        }

        ExternalLoginData externalData = ExternalLoginData.FromIdentity(ticket.Identity);

        if (externalData == null)
        {
            return BadRequest("The external login is already associated with an account.");
        }

        IdentityResult result = await UserManager.AddLoginAsync(User.Identity.GetUserId(),
            new UserLoginInfo(externalData.LoginProvider, externalData.ProviderKey));

        IHttpActionResult errorResult = GetErrorResult(result);

        if (errorResult != null)
        {
            return errorResult;
        }

        return Ok();
    }

    // POST api/Account/RemoveLogin
    [Route("RemoveLogin")]
    public async Task<IHttpActionResult> RemoveLogin(RemoveLoginBindingModel model)
    {
        if (!ModelState.IsValid)
        {
            return BadRequest(ModelState);
        }

        IdentityResult result;

        if (model.LoginProvider == LocalLoginProvider)
        {
            result = await UserManager.RemovePasswordAsync(User.Identity.GetUserId());
        }
        else
        {
            result = await UserManager.RemoveLoginAsync(User.Identity.GetUserId(),
                new UserLoginInfo(model.LoginProvider, model.ProviderKey));
        }

        IHttpActionResult errorResult = GetErrorResult(result);

        if (errorResult != null)
        {
            return errorResult;
        }

        return Ok();
    }

    // GET api/Account/ExternalLogin
    [OverrideAuthentication]
    [HostAuthentication(DefaultAuthenticationTypes.ExternalCookie)]
    [AllowAnonymous]
    [Route("ExternalLogin", Name = "ExternalLogin")]
    public async Task<IHttpActionResult> GetExternalLogin(string provider, string error = null)
    {
        if (error != null)
        {
            return Redirect(Url.Content("~/") + "#error=" + Uri.EscapeDataString(error));
        }

        if (!User.Identity.IsAuthenticated)
        {
            return new ChallengeResult(provider, this);
        }

        ExternalLoginData externalLogin = ExternalLoginData.FromIdentity(User.Identity as ClaimsIdentity);

        if (externalLogin == null)
        {
            return InternalServerError();
        }

        if (externalLogin.LoginProvider != provider)
        {
            Authentication.SignOut(DefaultAuthenticationTypes.ExternalCookie);
            return new ChallengeResult(provider, this);
        }

        IdentityUser user = await UserManager.FindAsync(new UserLoginInfo(externalLogin.LoginProvider,
            externalLogin.ProviderKey));

        bool hasRegistered = user != null;

        if (hasRegistered)
        {
            Authentication.SignOut(DefaultAuthenticationTypes.ExternalCookie);
            ClaimsIdentity oAuthIdentity = await UserManager.CreateIdentityAsync(user,
                OAuthDefaults.AuthenticationType);
            ClaimsIdentity cookieIdentity = await UserManager.CreateIdentityAsync(user,
                CookieAuthenticationDefaults.AuthenticationType);
            AuthenticationProperties properties = ApplicationOAuthProvider.CreateProperties(user.UserName);
            Authentication.SignIn(properties, oAuthIdentity, cookieIdentity);
        }
        else
        {
            IEnumerable<Claim> claims = externalLogin.GetClaims();
            ClaimsIdentity identity = new ClaimsIdentity(claims, OAuthDefaults.AuthenticationType);
            Authentication.SignIn(identity);
        }

        return Ok();
    }

    // GET api/Account/ExternalLogins?returnUrl=%2F&generateState=true
    [AllowAnonymous]
    [Route("ExternalLogins")]
    public IEnumerable<ExternalLoginViewModel> GetExternalLogins(string returnUrl, bool generateState = false)
    {
        IEnumerable<AuthenticationDescription> descriptions = Authentication.GetExternalAuthenticationTypes();
        List<ExternalLoginViewModel> logins = new List<ExternalLoginViewModel>();

        string state;

        if (generateState)
        {
            const int strengthInBits = 256;
            state = RandomOAuthStateGenerator.Generate(strengthInBits);
        }
        else
        {
            state = null;
        }

        foreach (AuthenticationDescription description in descriptions)
        {
            ExternalLoginViewModel login = new ExternalLoginViewModel
            {
                Name = description.Caption,
                Url = Url.Route("ExternalLogin", new
                {
                    provider = description.AuthenticationType,
                    response_type = "token",
                    client_id = Startup.PublicClientId,
                    redirect_uri = new Uri(Request.RequestUri, returnUrl).AbsoluteUri,
                    state = state
                }),
                State = state
            };
            logins.Add(login);
        }

        return logins;
    }

    // POST api/Account/Register
    [AllowAnonymous]
    [Route("Register")]
    public async Task<IHttpActionResult> Register(RegisterBindingModel model)
    {
        if (!ModelState.IsValid)
        {
            return BadRequest(ModelState);
        }

        IdentityUser user = new IdentityUser
        {
            UserName = model.UserName
        };

        IdentityResult result = await UserManager.CreateAsync(user, model.Password);
        IHttpActionResult errorResult = GetErrorResult(result);

        if (errorResult != null)
        {
            return errorResult;
        }

        return Ok();
    }

    // POST api/Account/RegisterExternal
    [OverrideAuthentication]
    [HostAuthentication(DefaultAuthenticationTypes.ExternalBearer)]
    [Route("RegisterExternal")]
    public async Task<IHttpActionResult> RegisterExternal(RegisterExternalBindingModel model)
    {
        if (!ModelState.IsValid)
        {
            return BadRequest(ModelState);
        }

        ExternalLoginData externalLogin = ExternalLoginData.FromIdentity(User.Identity as ClaimsIdentity);

        if (externalLogin == null)
        {
            return InternalServerError();
        }

        IdentityUser user = new IdentityUser
        {
            UserName = model.UserName
        };
        user.Logins.Add(new IdentityUserLogin
        {
            LoginProvider = externalLogin.LoginProvider,
            ProviderKey = externalLogin.ProviderKey
        });
        IdentityResult result = await UserManager.CreateAsync(user);
        IHttpActionResult errorResult = GetErrorResult(result);

        if (errorResult != null)
        {
            return errorResult;
        }

        return Ok();
    }

    protected override void Dispose(bool disposing)
    {
        if (disposing)
        {
            UserManager.Dispose();
        }

        base.Dispose(disposing);
    }

    #region Helpers

    private IAuthenticationManager Authentication
    {
        get { return Request.GetOwinContext().Authentication; }
    }

    private IHttpActionResult GetErrorResult(IdentityResult result)
    {
        if (result == null)
        {
            return InternalServerError();
        }

        if (!result.Succeeded)
        {
            if (result.Errors != null)
            {
                foreach (string error in result.Errors)
                {
                    ModelState.AddModelError("", error);
                }
            }

            if (ModelState.IsValid)
            {
                // No ModelState errors are available to send, so just return an empty BadRequest.
                return BadRequest();
            }

            return BadRequest(ModelState);
        }

        return null;
    }

    private class ExternalLoginData
    {
        public string LoginProvider { get; set; }
        public string ProviderKey { get; set; }
        public string UserName { get; set; }

        public IList<Claim> GetClaims()
        {
            IList<Claim> claims = new List<Claim>();
            claims.Add(new Claim(ClaimTypes.NameIdentifier, ProviderKey, null, LoginProvider));

            if (UserName != null)
            {
                claims.Add(new Claim(ClaimTypes.Name, UserName, null, LoginProvider));
            }

            return claims;
        }

        public static ExternalLoginData FromIdentity(ClaimsIdentity identity)
        {
            if (identity == null)
            {
                return null;
            }

            Claim providerKeyClaim = identity.FindFirst(ClaimTypes.NameIdentifier);

            if (providerKeyClaim == null || String.IsNullOrEmpty(providerKeyClaim.Issuer)
                || String.IsNullOrEmpty(providerKeyClaim.Value))
            {
                return null;
            }

            if (providerKeyClaim.Issuer == ClaimsIdentity.DefaultIssuer)
            {
                return null;
            }

            return new ExternalLoginData
            {
                LoginProvider = providerKeyClaim.Issuer,
                ProviderKey = providerKeyClaim.Value,
                UserName = identity.FindFirstValue(ClaimTypes.Name)
            };
        }
    }

    private static class RandomOAuthStateGenerator
    {
        private static RandomNumberGenerator _random = new RNGCryptoServiceProvider();

        public static string Generate(int strengthInBits)
        {
            const int bitsPerByte = 8;

            if (strengthInBits % bitsPerByte != 0)
            {
                throw new ArgumentException("strengthInBits must be evenly divisible by 8.", "strengthInBits");
            }

            int strengthInBytes = strengthInBits / bitsPerByte;

            byte[] data = new byte[strengthInBytes];
            _random.GetBytes(data);
            return HttpServerUtility.UrlTokenEncode(data);
        }
    }

    #endregion
}

Now, we can see that because it is using RoutePrefix that his is definitely version 2+ of WebApi. 现在,我们可以看到,因为它使用的是RoutePrefix ,所以他肯定是WebApi的2+版本。 My problem is that code does not compile. 我的问题是代码无法编译。 It states: 它指出:

The type or namespace name 'HostAuthenticationAttribute' could not be found (are you missing a using directive or an assembly reference?) 找不到类型或名称空间名称“ HostAuthenticationAttribute”(您是否缺少using指令或程序集引用?)

Looking at my clean project, I can see that this class resides in System.Web.Http.Owin . 查看我的干净项目,我可以看到该类位于System.Web.Http.Owin中 The problem is, I don't have that reference in my main project and I have no idea how to install it. 问题是,我的主项目中没有该参考,也不知道如何安装。

I have tried installing all the other different versions of the WebApi to no avail. 我尝试安装所有其他不同版本的WebApi均无济于事。

Surely someone has had this issue before? 肯定有人曾经遇到过这个问题吗?

I experienced the same error when trying to upgrade my WebAPI project to version 2.0. 尝试将WebAPI项目升级到2.0版时,我遇到了相同的错误。 Installing the nuget package Microsoft.AspNet.WebApi.Owin resolved the missing reference. 安装nuget包Microsoft.AspNet.WebApi.Owin解决了缺少的参考。

Install-Package Microsoft.AspNet.WebApi.Owin

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM