System.Web.Http。Owin WebApi2安装问题

时间:2022-02-05 13:31:27

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. This can be really frustrating when trying to add things to an existing project.....

我在。net和NUGet中发现的一件烦人的事情是,我不知道默认安装的是什么版本。当尝试向现有的项目添加东西时,这真的很令人沮丧……

Here is my current dilemma.

这是我目前的困境。

I have an MVC 5 project with only MVC on it. 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.

我有一个只有MVC的MVC 5项目。这个项目非常庞大,将它转移到另一个项目将花费太多的时间。于是,我打开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. It looks like this:

然后我创建了我的AccountController,它直接从我创建的clean项目中复制。它看起来像这样:

[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. My problem is that code does not compile. It states:

现在,我们可以看到,因为它使用的是RoutePrefix,他的绝对是WebApi的2+版本。我的问题是代码不能编译。州:

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. The problem is, I don't have that reference in my main project and I have no idea how to install it.

查看我的clean项目,我可以看到这个类驻留在System.Web.Http.Owin中。问题是,我的主项目中没有这个参考,我不知道如何安装它。

I have tried installing all the other different versions of the WebApi to no avail.

我已经尝试安装所有其他不同版本的WebApi,但没有效果。

Surely someone has had this issue before?

肯定有人以前有过这个问题吧?

1 个解决方案

#1


34  

I experienced the same error when trying to upgrade my WebAPI project to version 2.0. Installing the nuget package Microsoft.AspNet.WebApi.Owin resolved the missing reference.

当我试图将WebAPI项目升级到2.0版本时,也遇到了同样的错误。安装nuget包Microsoft.AspNet.WebApi。Owin解决了丢失的引用。

Install-Package Microsoft.AspNet.WebApi.Owin

#1


34  

I experienced the same error when trying to upgrade my WebAPI project to version 2.0. Installing the nuget package Microsoft.AspNet.WebApi.Owin resolved the missing reference.

当我试图将WebAPI项目升级到2.0版本时,也遇到了同样的错误。安装nuget包Microsoft.AspNet.WebApi。Owin解决了丢失的引用。

Install-Package Microsoft.AspNet.WebApi.Owin