In this episode I restructure a bit in order to clean things up some. I also tweak the site to redo the routing - something I think that went a little awry on me :). Finally, I add PayPal as a checkout option.
Routing Can Be Tricky
The MVC team did an exceptional job with the Routing engine and I did a less than stellar job of implementing a good routing scheme. As you'll see in this episode, it got to the point where I had a bit of "route spaghetti" in an effort to make my URLs as pretty as possible. You'll see me fix this - something I should have done a while ago - and restore routing to its default state.
One of the very cool things about resetting the routing is that I didn't need to do *any* work to the Views - the ActionLink and Url.Action methods worked flawlessly and I didn't need to update any links. That's awesome :) and a hat-tip goes to Eilon and Phil for that!
PayPal
I want to be sure that implementing a "store for the masses" is bleedingly simple - and nothing is easier for a merchant to setup than accepting payments from PayPal. In this episode I add in PayPal Standard and show you how to setup a PayPal controller that works with PayPal's IPN and PDT. I also show you how to effectively send tax/shipping information to PayPal and catch it on the rebound.
Some Formatting Love
Finally - Rickey Rosario over at Razorfish/AvenueA sent me a patch for the HTML/CSS that both cleaned it up and made it look exceedingly pretty. He even included Yahoo's CSS Reset - which is very nice for resetting the default CSS settings. I can't thank him enough for his work!
This is a bit of a long one (about 50 minutes) - lots of information in here. After this I'm going to put my head down and crank out the rest of the site as I really would like to finish everything up.
Hope you enjoy!
The code Is here (SVN is here)
Thanks for the informative reply! I like the idea of having interchangeable sql.config files but what I'm really aiming for is to have SVN contain everything that is relevant. Essentially, what I'd like to be able to do is sit down at a new computer, checkout all of the files from the repository, build and view in a browser. I'd like to not have to remember to manually update a config file. Is this possible?
I've been playing around with hosting the development database from within SQLExpress and thus getting away from having an absolutely-pathed .MDF file in the App_Data directory. What I don't like about this situation is that the database is now effectively out of source (version) control. Thoughts?
Thanks, Brad.
Great screencast!
Well done for the finis of StoreFront ( now for final part 26).
regarding this screencast (part 22 of paypal)
you said there after the whole process went well with paypal that you: "harness test of the whole process"
can you show me how?
i just need to do so for my store site (check multiple users on the paypal process)
how can i do it ?
( i tried to do web test with vs 2008 on paypal , but it always fails)
thanks .
Zahi.
I'm having a few problems with intellisense for strong typed html.actionlinks<>.
If i write it inline in the view and start to do the lambda (x=>x.). When i hit dot nothing shows up. However, if i skip the lamda and put a comma and type the link name, then come back to the lambda, everything works as excepted.
This happens for me on two different machines.
Does this happen to you or anyone else??
Cheers.
Adam
It seems possible, although I haven't tried it. I don't use SQLExpress databases that much in my applications, but you should be able to set the path in the web.config/connectionStrings/connectionstring as something like this:
connectionString="Data Source=.\SQLEXPRESS;
AttachDbFilename="|DataDirectory|\[your db name].mdf";
Integrated Security=True;User Instance=True"
providerName="System.Data.SqlClient" />
This way it should work since it's relative to the application, not a file system. Again I haven't tried it so I could be talking out of my butt. :^)
I made a small app that uses the SQLExpress database and Linq to Sql and I use this connection string in my app and it works where ever I move it.
You can find my blog about it at: http://www.kingwilder.com/Blog/tabid/54/EntryID/9/Default.aspx
I hope this helps.
very weird.
There is an small error in the Luhn's Algorithm implementation for Credit card veriication.if is like this
for (int i = cardChars.Length - 1; i >= 0; i--)
{
if (alternate)
{
int.TryParse(cardChars[i].ToString(), out currentDigit);
currentDigit *= 2;
if (currentDigit > 9)
{
currentDigit -= 9;
}
}
sum += currentDigit;
alternate = !alternate;
}
I think it should be like this
for (int i = cardChars.Length - 1; i >= 0; i--)
{
int.TryParse(cardChars[i].ToString(), out currentDigit);
if (alternate)
{
int.TryParse(cardChars[i].ToString(), out currentDigit);
currentDigit *= 2;
if (currentDigit > 9)
{
currentDigit -= 9;
}
}
sum += currentDigit;
alternate = !alternate;
}
Was it intentional?
That said - I've made sure to check this when the order comes in. If it doesn't match the PDT (and IPN) throw - logging the error.
Great screencast, just from a security point of view when using paypal and having hidden inputs to store the data on the page in your example the hiking backpack was $50, if someone saved the webpage and then changed the hidden value to say $20 then submitted the form how will the backend know if the price they paid was the correct price or not? The paypal transaction will go through successfully but you will be short $30 what strategy can be used in this case?
Regards DotnetShadow
CatalogController_IndexMethod_ShouldReturn_Products_For_Parent1, This test fails because TestCatalogRepository is not filling products to the default category
OrderController_List_Should_Set_20_Orders_To_ViewData, this test fails because the action need a status filter in the request, if not, a null reference exception happen
OrderController_AddItem_ShouldRedirect, this test fails because RedirectResult type is compared to RedirectToRouteResult type
Hope this help
Nice screencast, however I dislike the way that you send the data to Pay Pal. This may be the only way to do it with their API (I have never used it), but putting that kind of information and logic in the view file seems wrong. Have a look at the Google Checkout API. They allow you to send all the information up as an XML document so everything is sent on the server, then they reply with a URL which you can redirect the user to. Not sure if PP offer this, however I would switch to it if they do to allow a more pluggable site model.
Looking forward to seeing the beta.
Amar
1) Why did you end up using numbers again? This is ReallyBad(tm) for SEO, afaik. I think it should be really important to continue using the product names in the routes for SEO.
2) What is the difference between IIS7 url rewrite ting module and the MVC routing? If we create MVC apps, is there a need to use the IIS7 url rewrite module .. and if so, where would we take advantage of it?
Lastly, what is there REST list of actions you refer to? eg. Edit/Show, etc...
Thanks again Rob - love your work!
I'm well aware of Google's API - but again I'm doing the same thing. With Google you send off an encrypted HTTP request (64-bit) that you have to translate to XML. It's a web request . Same thing.
The difference is that most people feel a lot safer when they're checking out with PayPal. You have to remember that NO ONE ever wants to give you their credit card number - it's considered a barrier to sale. Sometimes redirecting to PayPal is a good thing.
In terms of rewriting - you can just use Routing in MVC - no need to rewrite URLs.
I am currently working on a corporate intranet project at work and I'm really pushing for ASP.NET MVC. So far your screen casts have been VERY instrumental in getting us going in the right direction. I've mirrored the Storefront's folder structure but I'm running into a problem with the database portion of the development. Since I am working closely with another developer on this project, we have an SVN server for the source code. And here is where the big question comes in: what do you recommend is the 'best practice' for a paired ASP.NET MVC programming project which involves a SQL database? We'd like to be able to develop on our own computers (which Visual Studio 2008 does beautifully with the built in ASP.NET web server) without having to connect to a live SQL server.
My idea is to use a local SQLExpress (.MDF) database. This allows for us to place the database under version control (SVN) and work without fear of breaking the others' code. It also allows us to work efficiently from home/road/etc. But, using SQLExpress might lead to some issues like absolute-path connection strings which don't play nicely with SVN. We don't want to have to remember (or waste time debugging because we forgot) to update the connection strings every time we commit/update our code. Thus I am stuck in a quandary.
Any help is greatly appreciated!
Thanks, Brad.
I wasn't intending to collect/send card details from the site, and I absolutely agree that is the responsibility of Paypal etc to collect that. I just think getting the controller to send the data, rather than the form fields is nicer since we can test the mapping routines, and easily plug in other controllers for other payment providers. It may spawn from my disdain towards markup :)
Amar
A lot of developers feel the way you do - they don't like "losing control" to other sites. I can tell you, however, that it's become quite common for people to be redirected to PayPal to pay for stuff. In fact if I am presented with that choice, as a user, that's what I'll do every time. I don't want anyone to know anything about me really - especially my credit card. I spose what I'm saying is that devs don't like it, users do (mostly) :).
In terms of your disdain towards markup - what's wrong with markup?
I find markup a bit too heavy, especially when playing with code all day, the xml looks too bloated (like with Spring.NET etc). NHaml is sure a sight for sore, xml ridden, eyes :)
Thanks for considering (hopefully)!
:) also IE7 here (like Rob said, above).
However, one SEO item you can address easily is the default category. If users enter the wrong/bad/missing number for a category you should redirect back to the root (or to the default category) and not render the default category info. You are unnecessarily showing the same default category using multiple urls (duplicate content). In addition, since the default is usually the most important category, you are potentially really hurting your money maker.
I don't know if this will answer your question, but I move my applications around to different machine for testing and I have a separate config file for the connection strings and reference them in my apps web.config. Like this...
...
...
This is the sql.config file. This way you can have a different sql.config file on each machine you test on.
connectionString="Data Source=[Your server];
Database=[Your Database];
User ID=[Your UserID];
Password=[Your password];"
providerName="System.Data.SqlClient"/>
I hope this helps.
Great work on the Storefront and these screencasts, looking forward to seeing the Beta1 update.
I am having an issue with viewing your videos with the "flip4mac" wmv Quicktime plugin. I am using a Macbook and this plugin is less intensive on the cpu. I wanted to make note of it to see if anyone else has this problem. The video will usually start fine, but does not update/refresh the screen when you flip between Visual Studio, and a website, for example.
I sure this is a codec issue of some sort, but Microsoft promotes this plugin as a way to view windows media files via the Mac. Please pass along....
Thanks
Faisal
iterate it and it applies the filtering in the DB.
public class AspNetAuthenticationService: IAuthenticationService{
public bool IsValidLogin(string userName, string password) {
ForumMemProvider ip = new ForumMemProvider();
return ip.ValidateUser(userName, password);
}
public class CustomMemProvider : MembershipProvider {
public override bool ValidateUser(string username, string password) { linq to sql statement to the data project via a repository here }
}
is one of em and so is NHib. I know a few others are also coming along (but
they're not free)
Was it intentional?
Nice screencast, however I dislike the way that you send the data to Pay Pal. This may be the only way to do it with their API (I have never used it), but putting that kind of information and logic in the view file seems wrong. Have a look at the Google Checkout API. They allow you to send all the information up as an XML document so everything is sent on the server, then they reply with a URL which you can redirect the user to. Not sure if PP offer this, however I would switch to it if they do to allow a more pluggable site model.
Looking forward to seeing the beta.
Amar
I'm well aware of Google's API - but again I'm doing the same thing. With Google you send off an encrypted HTTP request (64-bit) that you have to translate to XML. It's a web request . Same thing.
The difference is that most people feel a lot safer when they're checking out with PayPal. You have to remember that NO ONE ever wants to give you their credit card number - it's considered a barrier to sale. Sometimes redirecting to PayPal is a good thing.
I wasn't intending to collect/send card details from the site, and I absolutely agree that is the responsibility of Paypal etc to collect that. I just think getting the controller to send the data, rather than the form fields is nicer since we can test the mapping routines, and easily plug in other controllers for other payment providers. It may spawn from my disdain towards markup :)
Amar
A lot of developers feel the way you do - they don't like "losing control" to other sites. I can tell you, however, that it's become quite common for people to be redirected to PayPal to pay for stuff. In fact if I am presented with that choice, as a user, that's what I'll do every time. I don't want anyone to know anything about me really - especially my credit card. I spose what I'm saying is that devs don't like it, users do (mostly) :).
In terms of your disdain towards markup - what's wrong with markup?
I find markup a bit too heavy, especially when playing with code all day, the xml looks too bloated (like with Spring.NET etc). NHaml is sure a sight for sore, xml ridden, eyes :)
1) Why did you end up using numbers again? This is ReallyBad(tm) for SEO, afaik. I think it should be really important to continue using the product names in the routes for SEO.
2) What is the difference between IIS7 url rewrite ting module and the MVC routing? If we create MVC apps, is there a need to use the IIS7 url rewrite module .. and if so, where would we take advantage of it?
Lastly, what is there REST list of actions you refer to? eg. Edit/Show, etc...
Thanks again Rob - love your work!
In terms of rewriting - you can just use Routing in MVC - no need to rewrite URLs.
However, one SEO item you can address easily is the default category. If users enter the wrong/bad/missing number for a category you should redirect back to the root (or to the default category) and not render the default category info. You are unnecessarily showing the same default category using multiple urls (duplicate content). In addition, since the default is usually the most important category, you are potentially really hurting your money maker.
I am currently working on a corporate intranet project at work and I'm really pushing for ASP.NET MVC. So far your screen casts have been VERY instrumental in getting us going in the right direction. I've mirrored the Storefront's folder structure but I'm running into a problem with the database portion of the development. Since I am working closely with another developer on this project, we have an SVN server for the source code. And here is where the big question comes in: what do you recommend is the 'best practice' for a paired ASP.NET MVC programming project which involves a SQL database? We'd like to be able to develop on our own computers (which Visual Studio 2008 does beautifully with the built in ASP.NET web server) without having to connect to a live SQL server.
My idea is to use a local SQLExpress (.MDF) database. This allows for us to place the database under version control (SVN) and work without fear of breaking the others' code. It also allows us to work efficiently from home/road/etc. But, using SQLExpress might lead to some issues like absolute-path connection strings which don't play nicely with SVN. We don't want to have to remember (or waste time debugging because we forgot) to update the connection strings every time we commit/update our code. Thus I am stuck in a quandary.
Any help is greatly appreciated!
Thanks, Brad.
I don't know if this will answer your question, but I move my applications around to different machine for testing and I have a separate config file for the connection strings and reference them in my apps web.config. Like this...
<?xml version="1.0"?>
<configuration>
...
<connectionStrings configSource="sql.config"/>
...
</configuration>
This is the sql.config file. This way you can have a different sql.config file on each machine you test on.
<?xml version="1.0" encoding="utf-8" ?>
<connectionStrings>
<clear/>
<add name="MyConnection"
connectionString="Data Source=[Your server];
Database=[Your Database];
User ID=[Your UserID];
Password=[Your password];"
providerName="System.Data.SqlClient"/>
</connectionStrings>
I hope this helps.
Thanks for the informative reply! I like the idea of having interchangeable sql.config files but what I'm really aiming for is to have SVN contain everything that is relevant. Essentially, what I'd like to be able to do is sit down at a new computer, checkout all of the files from the repository, build and view in a browser. I'd like to not have to remember to manually update a config file. Is this possible?
I've been playing around with hosting the development database from within SQLExpress and thus getting away from having an absolutely-pathed .MDF file in the App_Data directory. What I don't like about this situation is that the database is now effectively out of source (version) control. Thoughts?
Thanks, Brad.
It seems possible, although I haven't tried it. I don't use SQLExpress databases that much in my applications, but you should be able to set the path in the web.config/connectionStrings/connectionstring as something like this:
<connectionStrings>
<add name="[Your connectionstring name]"
connectionString="Data Source=.SQLEXPRESS;
AttachDbFilename="|DataDirectory|[your db name].mdf";
Integrated Security=True;User Instance=True"
providerName="System.Data.SqlClient" />
</connectionStrings>
This way it should work since it's relative to the application, not a file system. Again I haven't tried it so I could be talking out of my butt. :^)
I made a small app that uses the SQLExpress database and Linq to Sql and I use this connection string in my app and it works where ever I move it.
You can find my blog about it at: http://www.kingwilder.com/Blog/tabid/54/EntryID...
I hope this helps.
:) also IE7 here (like Rob said, above).
CatalogController_IndexMethod_ShouldReturn_Products_For_Parent1, This test fails because TestCatalogRepository is not filling products to the default category
OrderController_List_Should_Set_20_Orders_To_ViewData, this test fails because the action need a status filter in the request, if not, a null reference exception happen
OrderController_AddItem_ShouldRedirect, this test fails because RedirectResult type is compared to RedirectToRouteResult type
Hope this help
I'm having a few problems with intellisense for strong typed html.actionlinks<>.
If i write it inline in the view and start to do the lambda (x=>x.). When i hit dot nothing shows up. However, if i skip the lamda and put a comma and type the link name, then come back to the lambda, everything works as excepted.
This happens for me on two different machines.
Does this happen to you or anyone else??
Cheers.
Adam
very weird.
There is an small error in the Luhn's Algorithm implementation for Credit card veriication.if is like this
for (int i = cardChars.Length - 1; i >= 0; i--)
{
if (alternate)
{
int.TryParse(cardChars[i].ToString(), out currentDigit);
currentDigit *= 2;
if (currentDigit > 9)
{
currentDigit -= 9;
}
}
sum += currentDigit;
alternate = !alternate;
}
I think it should be like this
for (int i = cardChars.Length - 1; i >= 0; i--)
{
int.TryParse(cardChars[i].ToString(), out currentDigit);
if (alternate)
{
int.TryParse(cardChars[i].ToString(), out currentDigit);
currentDigit *= 2;
if (currentDigit > 9)
{
currentDigit -= 9;
}
}
sum += currentDigit;
alternate = !alternate;
}
Great screencast, just from a security point of view when using paypal and having hidden inputs to store the data on the page in your example the hiking backpack was $50, if someone saved the webpage and then changed the hidden value to say $20 then submitted the form how will the backend know if the price they paid was the correct price or not? The paypal transaction will go through successfully but you will be short $30 what strategy can be used in this case?
Regards DotnetShadow
That said - I've made sure to check this when the order comes in. If it doesn't match the PDT (and IPN) throw - logging the error.
Thanks for considering (hopefully)!
Great work on the Storefront and these screencasts, looking forward to seeing the Beta1 update.
I am having an issue with viewing your videos with the "flip4mac" wmv Quicktime plugin. I am using a Macbook and this plugin is less intensive on the cpu. I wanted to make note of it to see if anyone else has this problem. The video will usually start fine, but does not update/refresh the screen when you flip between Visual Studio, and a website, for example.
I sure this is a codec issue of some sort, but Microsoft promotes this plugin as a way to view windows media files via the Mac. Please pass along....
Thanks
Faisal
iterate it and it applies the filtering in the DB.
is one of em and so is NHib. I know a few others are also coming along (but
they're not free)
public class AspNetAuthenticationService: IAuthenticationService{
public bool IsValidLogin(string userName, string password) {
ForumMemProvider ip = new ForumMemProvider();
return ip.ValidateUser(userName, password);
}
public class CustomMemProvider : MembershipProvider {
public override bool ValidateUser(string username, string password) { linq to sql statement to the data project via a repository here }
}
Great screencast!
Well done for the finis of StoreFront ( now for final part 26).
regarding this screencast (part 22 of paypal)
you said there after the whole process went well with paypal that you: "harness test of the whole process"
can you show me how?
i just need to do so for my store site (check multiple users on the paypal process)
how can i do it ?
( i tried to do web test with vs 2008 on paypal , but it always fails)
thanks .
Zahi.