Customize authentication to my own set of tables in asp.net web api 2?

by sunil ravulapalli /20. December 2013 03:32 /asp.net-web-api /Comments (0)

Assuming your table is called AppUser, convert your own AppUser domain object to IUser(using Microsoft.AspNet.Identity) like this

using Microsoft.AspNet.Identity; 
public class AppUser : IUser 
{ 
    //Existing database fields 
    public long AppUserId { get; set; } 
    public long AppUserName { get; set; } 
    public string AppPassword { get; set; } 
    [NotMapped] 
    public virtual string Id 
    { 
       get
       {
          return AppUserId;
       } 
    } 
    [NotMapped] 
    public string UserName 
    { 
        get { return AppUserName; } 
        set { AppUserName = value; } 
    } 
}

Implement the UserStore object like this

	using Microsoft.AspNet.Identity;
	public class UserStoreService : 
		IUserStore<AppUser>, IUserPasswordStore<AppUser>, 
		IUserSecurityStampStore<AppUser>
	{
		CompanyDbContext context = new CompanyDbContext();

		public Task CreateAsync(AppUser user)
		{            
			throw new NotImplementedException();
		}

		public Task DeleteAsync(AppUser user)
		{
			throw new NotImplementedException();
		}

		public Task<AppUser> FindByIdAsync(string userId)
		{
			throw new NotImplementedException();
		}

		public Task<AppUser> FindByNameAsync(string userName)
		{
			Task<AppUser> task = 
			context.AppUsers.Where(apu => apu.AppUserName == userName)
			.FirstOrDefaultAsync();

			return task;
		}

		public Task UpdateAsync(AppUser user)
		{
			throw new NotImplementedException();
		}

		public void Dispose()
		{
			context.Dispose();
		}

		public Task<string> GetPasswordHashAsync(AppUser user)
		{
			if (user == null)
			{
				throw new ArgumentNullException("user");
			}

			return Task.FromResult(user.AppPassword);
		}

		public Task<bool> HasPasswordAsync(AppUser user)
		{
			return Task.FromResult(user.AppPassword != null);
		}

		public Task SetPasswordHashAsync(AppUser user, string passwordHash)
		{
			throw new NotImplementedException();
		}

		public Task<string> GetSecurityStampAsync(AppUser user)
		{
			throw new NotImplementedException();
		}

		public Task SetSecurityStampAsync(AppUser user, string stamp)
		{
			throw new NotImplementedException();
		}
	}

If you have your own custom password hashing you will also need to implement IPasswordHasher. Below is an example where there is no hashing of the password(Oh no!)

	using Microsoft.AspNet.Identity;
	public class MyPasswordHasher : IPasswordHasher
	{
		public string HashPassword(string password)
		{
			return password;
		}

		public PasswordVerificationResult VerifyHashedPassword
		(string hashedPassword, string providedPassword)
		{
			if (hashedPassword == HashPassword(providedPassword))
				return PasswordVerificationResult.Success;
			else
				return PasswordVerificationResult.Failed;
		}
	}

In Startup.Auth.cs replace

	UserManagerFactory = () => 
		new UserManager<IdentityUser>(new UserStore<IdentityUser>());

with

	UserManagerFactory = () => 
                new UserManager<AppUser>(new UserStoreService()) { PasswordHasher = new MyPasswordHasher() };

In ApplicationOAuthProvider.cs, replace IdentityUser with AppUser In AccountController.cs, replace IdentityUser with AppUser and delete all the external authentication methods like GetManageInfo and RegisterExternal etc.

'System.Linq.IQueryable<Microsoft.AspNet.Identity.EntityFramework.IdentityUser>' does not contain a definition for 'FirstOrDefaultAsync'

by sunil ravulapalli /18. December 2013 08:40 /entityframework /Comments (0)

If you get the following error

'System.Linq.IQueryable<Microsoft.AspNet.Identity.EntityFramework.IdentityUser>' does not contain a definition for 'FirstOrDefaultAsync' and no extension method 'FirstOrDefaultAsync'
accepting a first argument of type 'System.Linq.IQueryable<Microsoft.AspNet.Identity.EntityFramework.IdentityUser>' could be found (are you missing a using directive or an assembly reference?) 

For some reason visual studio is not able to help in adding the reference automatically using "Ctrl +." shortcut. You need to add in the following namespace to get this to work.

using System.Data.Entity;

 

How to call an Authenticated Web Api 2 method

by sunil ravulapalli /18. December 2013 08:28 /asp.net-web-api /Comments (0)

Do a HTTP GET on the this URL

http://localhost:15718/api/Account/UserInfo

with the HTTP HEADER

Authorization: Bearer zt3Ma_gzOxRi53YgCciMe1H1j6Uss.........

The bearer token is from login using http://localhost/token. You can get more information here.

You should get a HTTP RESPONSE 200 with following data

{
    "UserName":"johnsmith",
    "HasRegistered":true,
    "LoginProvider": null
}

How to do User Login into Web Api 2

by sunil ravulapalli /18. December 2013 08:22 /asp.net-web-api /Comments (0)


Do a HTTP POST to the URL

http://localhost/token

with the HTTP HEADER

content-type: application/x-www-form-urlencoded

and HTTP BODY

username=johnsmith&password=supersecret&grant_type=password

You should get HTTP RESPONSE 200 and return data as

{
    "access_token":"zt3Ma_gzOxRi53YgCciMe1H1j6Uss...........",
    "token_type":"bearer",
    "expires_in":1209599,
    "userName":"sunil",
    ".issued":"Tue, 17 Dec 2013 17:58:05 GMT",
    ".expires":"Tue, 31 Dec 2013 17:58:05 GMT"
}

How to do User Registration using Web Api 2

by sunil ravulapalli /18. December 2013 08:15 /asp.net-web-api /Comments (0)

Do a HTTP POST to the URL 

http://localhost/api/Account/Register

with HTTP HEADER

content-type: application/json

and the HTTP BODY

{
  "UserName": "johnsmith",
  "Password": "supersecret",
  "ConfirmPassword": "supersecret"
}

You should get a HTTP RESPONSE 200

Xbox One Initial Review

by sunil ravulapalli /3. December 2013 09:20 /games /Comments (0)

I got lucky getting the Xbox One at midnight on release night. I've been using it for almost  two weeks now and I am mostly happy with the purchase.

Hardware:

Nothing much to say here. It is pretty big but I don't think it is ugly to look at. In fact, the new buttons kind of have a futuristic feel to it.

Software OS:

The OS looks beautiful. Mostly, fluid and fast, but occasionally slows down for a few seconds but recovers its' fluidity.

Market Place:

The market place looks a little sparse. But it has YouTube and Netflix, so good enough for me. The Netflix app looks like the one on windows 8. I am not a fan of the YouTube app. The one on Xbox 360 is better. 

Games:

The only game I played on it Call of duty: Ghosts. It looks the same as the one on the Xbox 360.

Cable:

I did plug in my cable box into the Xbox One. It is a decent experience. The voice commands like "Xbox One guide" or "Xbox Watch CBS" work nicely. But if you just want to scroll through the guide to find something interesting to watch you need to pick up the controller. I wish they made a remote which I can operate with a single hand.

 

 

ASP.NET Web Api custom IHttpActionResult for HTTP Forbidden

by sunil ravulapalli /13. November 2013 06:06 /asp.net-web-api /Comments (0)
    public class ForbiddenActionResult : IHttpActionResult
    {
        private readonly HttpRequestMessage _request;
        private readonly string _reason;
        public ForbiddenActionResult(HttpRequestMessage request, string reason)
        {
            _request = request;
            _reason = reason;
        }

        public Task<HttpResponseMessage> ExecuteAsync(CancellationToken cancellationToken)
        {
            var response = _request.CreateResponse(HttpStatusCode.Forbidden, _reason);
            return Task.FromResult(response);
        }
    }

You can use it like this:

public IHttpActionResult Get(long accountId)
{
    var payOffQuoteStatus = _payOffQuoteService.GetPayOffQuote(accountId);

    if (payOffQuoteStatus.IsEligibleForPayOffQuote)
          return Ok(payOffQuoteStatus.PayOffQuote);
    else
          return new ForbiddenActionResult(Request, payOffQuoteStatus.ReasonForIneligibility);
}

Unit Test ASP.NET Web Api IHttpActionResult

by sunil ravulapalli /13. November 2013 05:57 /asp.net-web-api /Comments (0)

Suppose the web api action looks like this

public IHttpActionResult Get(long accountId) 
{ 
       var payOffQuoteStatus = _payOffQuoteService.GetPayOffQuote(accountId); 

       return Ok<PayOffQuote>(payOffQuoteStatus.PayOffQuote); 
}

then the test would look like this

            //Arrange
            var payOffQuoteServiceMock = new Mock<IPayOffQuoteService>();
            payOffQuoteServiceMock.Setup(poqs => poqs.GetPayOffQuote(It.IsAny<long>()))
                                  .Returns(new PayOffQuoteStatus
                                      {
                                          IsEligibleForPayOffQuote = true,
                                          PayOffQuote = new PayOffQuote {BalanceOutstanding = 14225.68m}
                                      });
            var payOffController = new PayoffQuoteController(payOffQuoteServiceMock.Object);
            payOffController.Request = new HttpRequestMessage();
            payOffController.Request.Properties.Add(HttpPropertyKeys.HttpConfigurationKey, new HttpConfiguration());
            
            //Act
            var httpActionResult = payOffController.Get(12345678);

            //Assert
            OkNegotiatedContentResult<PayOffQuote> contentResult = httpActionResult as OkNegotiatedContentResult<PayOffQuote>;
            Assert.IsNotNull(contentResult);

            var payOffQuote = contentResult.Content as PayOffQuote;
            Assert.IsNotNull(payOffQuote);
            Assert.AreEqual(14225.68m, payOffQuote.BalanceOutstanding);

Unit test ASP.NET Web Api attrubute routing

by sunil ravulapalli /13. November 2013 03:50 /asp.net-web-api /Comments (0)

Most of the stuff is standard expect you need to call config.EnsureInitialized() after WebApiConfig.Register(config)

            //Arrange            
            var request = new HttpRequestMessage(HttpMethod.Get, "http://localhost.com/api/v1/account/12345678/info");
            var config = new HttpConfiguration();

            //Act
            WebApiConfig.Register(config);
            config.EnsureInitialized();
            var route = WebApi.RouteRequest(config, request);

            //Assert
            Assert.AreEqual("InfoController", route.Controller.Name);
            Assert.AreEqual("Get", route.Action);

System.InvalidOperationException: No Entity Framework provider found for the ADO.NET provider with invariant name 'System.Data.SqlClient'.

by sunil ravulapalli /12. November 2013 09:17 /entityframework /Comments (0)

I got this error when using Entity framework 6.0 from my MSTest project:

System.InvalidOperationException: No Entity Framework provider found for the ADO.NET provider with invariant name 'System.Data.SqlClient'. Make sure the provider is registered in the 'entityFramework' section of the application config file. See http://go.microsoft.com/fwlink/?LinkId=260882 for more information.

To fix this put

var _temp = System.Data.Entity.SqlServer.SqlProviderServices.Instance;

anywhere in your test project. I put it in a constructor.

Reference:

http://entityframework.codeplex.com/workitem/1590