title: System.Web.Http.Owin WebApi2 installation woes
body: <p>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.....</p>
  
  <p>Here is my current dilemma.</p>
  
  <p>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.</p>
  
  <p>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.</p>
  
  <p>Then I came to create my AccountController which is just copied straight from the clean project I created. It looks like this:</p>
  
  <pre><code>[Authorize]
  [RoutePrefix("api/Account")]
  public class AccountController : ApiController
  {
      private const string LocalLoginProvider = "Local";
  
      public AccountController()
          : this(Startup.UserManagerFactory(), Startup.OAuthOptions.AccessTokenFormat)
      {
      }
  
      public AccountController(UserManager&lt;IdentityUser&gt; userManager,
          ISecureDataFormat&lt;AuthenticationTicket&gt; accessTokenFormat)
      {
          UserManager = userManager;
          AccessTokenFormat = accessTokenFormat;
      }
  
      public UserManager&lt;IdentityUser&gt; UserManager { get; private set; }
      public ISecureDataFormat&lt;AuthenticationTicket&gt; 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&amp;generateState=true
      [Route("ManageInfo")]
      public async Task&lt;ManageInfoViewModel&gt; GetManageInfo(string returnUrl, bool generateState = false)
      {
          IdentityUser user = await UserManager.FindByIdAsync(User.Identity.GetUserId());
  
          if (user == null)
          {
              return null;
          }
  
          List&lt;UserLoginInfoViewModel&gt; logins = new List&lt;UserLoginInfoViewModel&gt;();
  
          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&lt;IHttpActionResult&gt; 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&lt;IHttpActionResult&gt; 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&lt;IHttpActionResult&gt; 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
              &amp;&amp; ticket.Properties.ExpiresUtc.HasValue
              &amp;&amp; ticket.Properties.ExpiresUtc.Value &lt; 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&lt;IHttpActionResult&gt; 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&lt;IHttpActionResult&gt; 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&lt;Claim&gt; claims = externalLogin.GetClaims();
              ClaimsIdentity identity = new ClaimsIdentity(claims, OAuthDefaults.AuthenticationType);
              Authentication.SignIn(identity);
          }
  
          return Ok();
      }
  
      // GET api/Account/ExternalLogins?returnUrl=%2F&amp;generateState=true
      [AllowAnonymous]
      [Route("ExternalLogins")]
      public IEnumerable&lt;ExternalLoginViewModel&gt; GetExternalLogins(string returnUrl, bool generateState = false)
      {
          IEnumerable&lt;AuthenticationDescription&gt; descriptions = Authentication.GetExternalAuthenticationTypes();
          List&lt;ExternalLoginViewModel&gt; logins = new List&lt;ExternalLoginViewModel&gt;();
  
          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&lt;IHttpActionResult&gt; 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&lt;IHttpActionResult&gt; 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&lt;Claim&gt; GetClaims()
          {
              IList&lt;Claim&gt; claims = new List&lt;Claim&gt;();
              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
  }
  </code></pre>
  
  <p>Now, we can see that because it is using <strong>RoutePrefix</strong> that his is definitely version 2+ of WebApi.
  My problem is that code does not compile. It states:</p>
  
  <blockquote>
    <p>The type or namespace name 'HostAuthenticationAttribute' could not be found (are you missing a using directive or an assembly reference?)</p>
  </blockquote>
  
  <p>Looking at my clean project, I can see that this class resides in <strong>System.Web.Http.Owin</strong>. The problem is, I don't have that reference in my main project and I have no idea how to install it.</p>
  
  <p>I have tried installing all the other different versions of the WebApi to no avail.</p>
  
  <p>Surely someone has had this issue before?</p>