tag:blogger.com,1999:blog-56172843240045215652024-03-19T21:04:02.241-07:00What happened to My-MSI.netErichttp://www.blogger.com/profile/02676710416649644137noreply@blogger.comBlogger33125tag:blogger.com,1999:blog-5617284324004521565.post-24839185395226986012013-01-08T17:16:00.002-08:002013-01-08T17:17:05.400-08:00How to scroll a large text that doesn't scroll?How to scroll a large text that doesn't scroll?<br />
<br />
Just add this css element:<br />
<br />
overflow: visible;<br />
<span style="font-family: Consolas; font-size: x-small;"><span style="font-family: Consolas; font-size: x-small;">
</span></span>Erichttp://www.blogger.com/profile/02676710416649644137noreply@blogger.com0tag:blogger.com,1999:blog-5617284324004521565.post-75099232116922993052013-01-07T17:04:00.000-08:002013-01-07T17:11:49.071-08:00Need a Logout link on every page of your MVC 3 web site?Need a Logout link on every page of your MVC 3 web site? This is fairly easy to do:<br />
<br />
First thing to do is add a new Logout member of your Controller class as:<br />
<br />
<br />
public PartialViewResult Logout(){ AdminData data = new AdminData( AccountController.OnlineUsers.Count ); return PartialView( data );}<br />
<br />
What is AdminData? Just a small class that holds a number:<br />
<br />
public class AdminData{<br />
public decimal LoggedInUsers { get; set; }<br />
public AdminData( decimal loggedInUsers )<br /> {<br />
LoggedInUsers = loggedInUsers;<br />
}<br />
}<br />
<br />
What should be in the view? Just this:<br />
<br />
@model My_MSI.Net.Areas.Admin.Models.Entities.AdminData<br />
@using ( Ajax.BeginForm( "OnlineUsers", "BackOffice", new { area = "" }, new AjaxOptions { UpdateTargetId = "onlineUsers", HttpMethod = "Post" } ) )<br />
{<br />
<table width="95%"><br />
<tr><br />
<td style="text-align: right; width: 90%;"><br />
<span style="text-align: right;">We currently have<br />
AjaxExtensions.ActionLink( Ajax, @Model.LoggedInUsers.ToString),<br />
"OnlineUsers", "BackOffice", <br />
new { area = "" },<br />
new AjaxOptions { UpdateTargetId = "onlineUsers", HttpMethod = "Post" } )<br />
user(s) logged in.</span><br />
</td><br />
<td style="text-align: right; width: 10%;"><br />
@Html.ActionLink( Log Out", "LogOff", "BackOffice", new { area = "" }, null )<br />
</td><br />
</tr><br />
</table>}<br />
<br />
This view may be more complicated than you want. Let me explain what it is doing:<br />
<br />
The <td> with a <span ....>...</span> in it is actually an Unobtrusive AJAX link as the number of users currently logged into the BackOffice (password protected part of the site).<br />
<br />
We put the LogOff member in a base class that all controllers derrive from and it looks like this:<br />
<br />
public RedirectToRouteResult LogOff()<br />
{<br />
if ( AccountController.OnlineUsers.Count >= 1 )<br />
{ LoggedInUsers member = AccountController.OnlineUsers<br />
.First( m => m.MemberName == User.Identity.Name );<br />
if ( member != null )<br />
AccountController.OnlineUsers.Remove( member );<br />
}<br />
FormsAuthentication.SignOut();<br />
return RedirectToAction( "Index", "Home",<br />
new { MemberName = User.Identity.Name, area = "" } );<br />
}<br />
<br />
This processing takes place within the if (...) { } block:<br />
We check the number of OnlineUsers in the first if( AcountController.OnlineUsers.Count >= 1 ) statement because if this list is empty we don't need to remove anyone.<br />
<br />
Next we find the LoggedInUsers record for the current User.Identity.Name because this is the logged in member name.<br />
<br />
Next we verify that the member is not null because that can happen sometimes.<br />
<br />
If and only if the member is not null, we remove that member from the AccountController.OnlineUsers list.<br />
<br />
Now we are outside the if() { } block:<br />
<br />
The first thing that you'll want to do is do a: FormsAuthentication.SingOut(); This signs out the user and removes that authentication cookie from the HTTP stream.<br />
<br />
Finally we need to RediredtToAction to the publicly accessable portion of the site.<br />
<br />
That's almost everything that you need to do to get a Logout link on every page of your site:<br />
<br />
The final step is:<br />
<br />
In your _Layout.cshtml file,<br />
<br />
Find this: <br />
<div class="content"><br />
@RenderBody()<br />
</div><br />
<br />
You want to add this above the @RenderBody() method:<br />
<br />
@{ Html.RenderAction( "Logout", "BackOffice" ); }<br />
<br />
That's everything you need to do to get a Logout link on every page of your site.<br />
<br />
<br />Erichttp://www.blogger.com/profile/02676710416649644137noreply@blogger.com0tag:blogger.com,1999:blog-5617284324004521565.post-82434842957280826702012-12-23T13:47:00.000-08:002012-12-23T13:47:14.821-08:00What happens if you need to test a user role where it isn't set up yet?In my AccountController's LogIn method, since I've added Role based authentication to the site,<br />
I wanted to use User.IsInRole( "Admin" ) to check for an Admin role.<br />
<br />
Of course that doesn't work!<br />
<br />
So instead, I had to do this:<br />
<span style="font-family: Consolas; font-size: x-small;"><span style="font-family: Consolas; font-size: x-small;"> </span><br /></span><span style="color: blue; font-family: Consolas; font-size: x-small;"><span style="color: blue; font-family: Consolas; font-size: x-small;"><span style="color: blue; font-family: Consolas; font-size: x-small;">decimal</span></span></span><span style="font-family: Consolas; font-size: x-small;"><span style="font-family: Consolas; font-size: x-small;"> id = </span></span><span style="color: #2b91af; font-family: Consolas; font-size: x-small;"><span style="color: #2b91af; font-family: Consolas; font-size: x-small;"><span style="color: #2b91af; font-family: Consolas; font-size: x-small;">Identity</span></span></span><span style="font-family: Consolas; font-size: x-small;"><span style="font-family: Consolas; font-size: x-small;">.LookupId( details.MemberName, db );</span></span><br />
<span style="color: #2b91af; font-family: Consolas; font-size: x-small;"><span style="color: #2b91af; font-family: Consolas; font-size: x-small;"><span style="color: #2b91af; font-family: Consolas; font-size: x-small;">Identity</span></span></span><span style="font-family: Consolas; font-size: x-small;"><span style="font-family: Consolas; font-size: x-small;"> Id = </span></span><span style="color: #2b91af; font-family: Consolas; font-size: x-small;"><span style="color: #2b91af; font-family: Consolas; font-size: x-small;"><span style="color: #2b91af; font-family: Consolas; font-size: x-small;">Identity</span></span></span><span style="font-family: Consolas; font-size: x-small;"><span style="font-family: Consolas; font-size: x-small;">.Load( id, db );</span></span><br />
<span style="color: blue; font-family: Consolas; font-size: x-small;"><span style="color: blue; font-family: Consolas; font-size: x-small;"><span style="color: blue; font-family: Consolas; font-size: x-small;">if</span></span></span><span style="font-family: Consolas; font-size: x-small;"><span style="font-family: Consolas; font-size: x-small;">( Id.RoleIndex == 1 )</span></span><br />
<span style="font-family: Consolas; font-size: x-small;"><span style="font-family: Consolas; font-size: x-small;">
{<br />...</span></span><br />
<span style="font-family: Consolas; font-size: x-small;">}</span><br />
<br />
That's two hits to the database, but I do those two hits on almost every page so I know that the server can easily handle the task at hand.<br />
<br />
Why was I interested in this:<br />
<br />
Well we have two different controllers and I wanted the Admin role to be sent to the AdminController and normal Users to be sent to the BackOfficeContoller.<br />
<br />
Erichttp://www.blogger.com/profile/02676710416649644137noreply@blogger.com0tag:blogger.com,1999:blog-5617284324004521565.post-53787816555925163382012-12-19T08:08:00.001-08:002012-12-20T04:41:27.706-08:00Ever want to create a list of logged in users for a site, maybe for the Admin view or all users?<br />
<br />
Here's how:<br />
<br />
In your AccountController add a simple class:<br />
<span style="font-family: Consolas; font-size: x-small;"></span><br />
<span style="font-family: Consolas; font-size: x-small;"></span><span style="color: blue; font-family: Consolas; font-size: x-small;"><span style="color: blue; font-family: Consolas; font-size: x-small;"><span style="color: blue; font-family: Consolas; font-size: x-small;">public</span></span></span><span style="font-family: Consolas; font-size: x-small;"><span style="font-family: Consolas; font-size: x-small;"> </span></span><span style="color: blue; font-family: Consolas; font-size: x-small;"><span style="color: blue; font-family: Consolas; font-size: x-small;"><span style="color: blue; font-family: Consolas; font-size: x-small;">class</span></span></span><span style="font-family: Consolas; font-size: x-small;"><span style="font-family: Consolas; font-size: x-small;"> </span></span><span style="color: #2b91af; font-family: Consolas; font-size: x-small;"><span style="color: #2b91af; font-family: Consolas; font-size: x-small;"><span style="color: #2b91af; font-family: Consolas; font-size: x-small;">LoggedInUsers</span></span></span><br />
<span style="font-family: Consolas; font-size: x-small;"><span style="font-family: Consolas; font-size: x-small;">{</span></span><br />
<span style="color: blue; font-family: Consolas; font-size: x-small;"><span style="color: blue; font-family: Consolas; font-size: x-small;"><span style="color: blue; font-family: Consolas; font-size: x-small;"> public</span></span></span><span style="font-family: Consolas; font-size: x-small;"><span style="font-family: Consolas; font-size: x-small;"> </span></span><span style="color: blue; font-family: Consolas; font-size: x-small;"><span style="color: blue; font-family: Consolas; font-size: x-small;"><span style="color: blue; font-family: Consolas; font-size: x-small;">string</span></span></span><span style="font-family: Consolas; font-size: x-small;"><span style="font-family: Consolas; font-size: x-small;"> MemberName { </span></span><span style="color: blue; font-family: Consolas; font-size: x-small;"><span style="color: blue; font-family: Consolas; font-size: x-small;"><span style="color: blue; font-family: Consolas; font-size: x-small;">get</span></span></span><span style="font-family: Consolas; font-size: x-small;"><span style="font-family: Consolas; font-size: x-small;">; </span></span><span style="color: blue; font-family: Consolas; font-size: x-small;"><span style="color: blue; font-family: Consolas; font-size: x-small;"><span style="color: blue; font-family: Consolas; font-size: x-small;">set</span></span></span><span style="font-family: Consolas; font-size: x-small;"><span style="font-family: Consolas; font-size: x-small;">; }</span></span><br />
<span style="color: blue; font-family: Consolas; font-size: x-small;"><span style="color: blue; font-family: Consolas; font-size: x-small;"><span style="color: blue; font-family: Consolas; font-size: x-small;"> public</span></span></span><span style="font-family: Consolas; font-size: x-small;"><span style="font-family: Consolas; font-size: x-small;"> </span></span><span style="color: #2b91af; font-family: Consolas; font-size: x-small;"><span style="color: #2b91af; font-family: Consolas; font-size: x-small;"><span style="color: #2b91af; font-family: Consolas; font-size: x-small;">DateTime</span></span></span><span style="font-family: Consolas; font-size: x-small;"><span style="font-family: Consolas; font-size: x-small;"> LoggedInTime { </span></span><span style="color: blue; font-family: Consolas; font-size: x-small;"><span style="color: blue; font-family: Consolas; font-size: x-small;"><span style="color: blue; font-family: Consolas; font-size: x-small;">get</span></span></span><span style="font-family: Consolas; font-size: x-small;"><span style="font-family: Consolas; font-size: x-small;">; </span></span><span style="color: blue; font-family: Consolas; font-size: x-small;"><span style="color: blue; font-family: Consolas; font-size: x-small;"><span style="color: blue; font-family: Consolas; font-size: x-small;">set</span></span></span><span style="font-family: Consolas; font-size: x-small;"><span style="font-family: Consolas; font-size: x-small;">; }</span></span><br />
<span style="font-family: Consolas; font-size: x-small;"><span style="font-family: Consolas; font-size: x-small;">
</span></span><br />
<span style="font-family: Consolas; font-size: x-small;"></span><span style="color: blue; font-family: Consolas; font-size: x-small;"><span style="color: blue; font-family: Consolas; font-size: x-small;"><span style="color: blue; font-family: Consolas; font-size: x-small;"> public</span></span></span><span style="font-family: Consolas; font-size: x-small;"><span style="font-family: Consolas; font-size: x-small;"> LoggedInUsers( </span></span><span style="color: blue; font-family: Consolas; font-size: x-small;"><span style="color: blue; font-family: Consolas; font-size: x-small;"><span style="color: blue; font-family: Consolas; font-size: x-small;">string</span></span></span><span style="font-family: Consolas; font-size: x-small;"><span style="font-family: Consolas; font-size: x-small;"> memberName, </span></span><span style="color: #2b91af; font-family: Consolas; font-size: x-small;"><span style="color: #2b91af; font-family: Consolas; font-size: x-small;"><span style="color: #2b91af; font-family: Consolas; font-size: x-small;">DateTime</span></span></span><span style="font-family: Consolas; font-size: x-small;"><span style="font-family: Consolas; font-size: x-small;"> loggedInTime )</span></span><br />
<span style="font-family: Consolas; font-size: x-small;"><span style="font-family: Consolas; font-size: x-small;"> {<br /> MemberName = memberName;<br /> LoggedInTime = loggedInTime;<br /> }<br />}</span></span><br />
<span style="font-family: Consolas; font-size: x-small;"></span><br />
<span style="font-family: Consolas; font-size: x-small;">Then in your AccountController add a:</span><br />
<span style="font-family: Consolas; font-size: x-small;"> </span><br />
<span style="font-family: Consolas; font-size: x-small;"><span style="color: blue; font-family: Consolas; font-size: x-small;"><span style="color: blue; font-family: Consolas; font-size: x-small;"><span style="color: blue; font-family: Consolas; font-size: x-small;">public</span></span></span><span style="font-family: Consolas; font-size: x-small;"><span style="font-family: Consolas; font-size: x-small;"> </span></span><span style="color: blue; font-family: Consolas; font-size: x-small;"><span style="color: blue; font-family: Consolas; font-size: x-small;"><span style="color: blue; font-family: Consolas; font-size: x-small;">static</span></span></span><span style="font-family: Consolas; font-size: x-small;"><span style="font-family: Consolas; font-size: x-small;"> </span></span><span style="color: #2b91af; font-family: Consolas; font-size: x-small;"><span style="color: #2b91af; font-family: Consolas; font-size: x-small;"><span style="color: #2b91af; font-family: Consolas; font-size: x-small;">List</span></span></span><span style="font-family: Consolas; font-size: x-small;"><span style="font-family: Consolas; font-size: x-small;"><</span></span><span style="color: #2b91af; font-family: Consolas; font-size: x-small;"><span style="color: #2b91af; font-family: Consolas; font-size: x-small;"><span style="color: #2b91af; font-family: Consolas; font-size: x-small;">LoggedInUsers</span></span></span><span style="font-family: Consolas; font-size: x-small;"><span style="font-family: Consolas; font-size: x-small;">> OnlineUsers;</span></span><br />
<br />
Then in your AccountController's [HtmlPost] Login(...) method add this line for authenticated users:<br />
<span style="font-family: Consolas; font-size: x-small;"> </span><br />
<span style="font-family: Consolas; font-size: x-small;"></span><span style="color: #2b91af; font-family: Consolas; font-size: x-small;"><span style="color: #2b91af; font-family: Consolas; font-size: x-small;"><span style="color: #2b91af; font-family: Consolas; font-size: x-small;">AccountController</span></span></span><span style="font-family: Consolas; font-size: x-small;"><span style="font-family: Consolas; font-size: x-small;">.OnlineUsers.Add( </span></span><span style="color: blue; font-family: Consolas; font-size: x-small;"><span style="color: blue; font-family: Consolas; font-size: x-small;"><span style="color: blue; font-family: Consolas; font-size: x-small;">new</span></span></span><span style="font-family: Consolas; font-size: x-small;"><span style="font-family: Consolas; font-size: x-small;"> </span></span><span style="color: #2b91af; font-family: Consolas; font-size: x-small;"><span style="color: #2b91af; font-family: Consolas; font-size: x-small;"><span style="color: #2b91af; font-family: Consolas; font-size: x-small;">LoggedInUsers</span></span></span><span style="font-family: Consolas; font-size: x-small;"><span style="font-family: Consolas; font-size: x-small;">( details.MemberName, </span></span><span style="color: #2b91af; font-family: Consolas; font-size: x-small;"><span style="color: #2b91af; font-family: Consolas; font-size: x-small;"><span style="color: #2b91af; font-family: Consolas; font-size: x-small;">DateTime</span></span></span><span style="font-family: Consolas; font-size: x-small;"><span style="font-family: Consolas; font-size: x-small;">.Now ) );</span></span><br />
<span style="font-family: Consolas; font-size: x-small;"><span style="font-family: Consolas; font-size: x-small;">
</span></span><br />
<span style="font-family: Consolas; font-size: x-small;"><span style="font-family: Consolas; font-size: x-small;">
This adds a new user to the OnlineUsers list.</span></span><br />
<br />
To remove a entry from the list:<br />
<br />
In your Logout() method (you have one of these, right?):<br />
<br />
Add this:<br />
<span style="font-family: Consolas; font-size: x-small;"><span style="font-family: Consolas; font-size: x-small;"></span> </span><br />
<span style="font-family: Consolas; font-size: x-small;"></span><span style="color: blue; font-family: Consolas; font-size: x-small;"><span style="color: blue; font-family: Consolas; font-size: x-small;"><span style="color: blue; font-family: Consolas; font-size: x-small;">if</span></span></span><span style="font-family: Consolas; font-size: x-small;"><span style="font-family: Consolas; font-size: x-small;"> ( </span></span><span style="color: #2b91af; font-family: Consolas; font-size: x-small;"><span style="color: #2b91af; font-family: Consolas; font-size: x-small;"><span style="color: #2b91af; font-family: Consolas; font-size: x-small;">AccountController</span></span></span><span style="font-family: Consolas; font-size: x-small;"><span style="font-family: Consolas; font-size: x-small;">.OnlineUsers.Count > 0 )</span></span></span><br />
{<br />
If( AccountController.OnlineUsers.Count > 0 )<br /> {<br />
LoggedInUsers member = AccountController.OnlineUsers.First( m => m.MemberName == User.Identity.Name );<br />
AccountController.OnlineUsers.Remove( member );<br /> } <br />
}<br />
<br />
Just before this:<br />
<span style="font-family: Consolas; font-size: x-small;"><span style="color: #2b91af; font-family: Consolas; font-size: x-small;"><span style="color: #2b91af; font-family: Consolas; font-size: x-small;"><span style="color: #2b91af; font-family: Consolas; font-size: x-small;"></span></span></span></span><br />
<span style="font-family: Consolas; font-size: x-small;"><span style="color: #2b91af; font-family: Consolas; font-size: x-small;"><span style="color: #2b91af; font-family: Consolas; font-size: x-small;"><span style="color: #2b91af; font-family: Consolas; font-size: x-small;">FormsAuthentication</span></span></span><span style="font-family: Consolas; font-size: x-small;"><span style="font-family: Consolas; font-size: x-small;">.SignOut();</span></span><br />
<span style="font-family: Consolas; font-size: x-small;"><span style="font-family: Consolas; font-size: x-small;">
</span></span></span><br />
There is one other place you'll need to add some code and that is in your global.asax Session_End method like this:<br />
<span style="font-family: Consolas; font-size: x-small;"><span style="font-family: Consolas; font-size: x-small;"></span></span><br />
<span style="color: blue; font-family: Consolas; font-size: x-small;"><span style="color: blue; font-family: Consolas; font-size: x-small;"><span style="color: blue; font-family: Consolas; font-size: x-small;">protected</span></span></span><span style="font-family: Consolas; font-size: x-small;"><span style="font-family: Consolas; font-size: x-small;"> </span></span><span style="color: blue; font-family: Consolas; font-size: x-small;"><span style="color: blue; font-family: Consolas; font-size: x-small;"><span style="color: blue; font-family: Consolas; font-size: x-small;">static</span></span></span><span style="font-family: Consolas; font-size: x-small;"><span style="font-family: Consolas; font-size: x-small;"> </span></span><span style="color: blue; font-family: Consolas; font-size: x-small;"><span style="color: blue; font-family: Consolas; font-size: x-small;"><span style="color: blue; font-family: Consolas; font-size: x-small;">void</span></span></span><span style="font-family: Consolas; font-size: x-small;"><span style="font-family: Consolas; font-size: x-small;"> Session_End( </span></span><span style="color: blue; font-family: Consolas; font-size: x-small;"><span style="color: blue; font-family: Consolas; font-size: x-small;"><span style="color: blue; font-family: Consolas; font-size: x-small;">object</span></span></span><span style="font-family: Consolas; font-size: x-small;"><span style="font-family: Consolas; font-size: x-small;"> Sender, </span></span><span style="color: #2b91af; font-family: Consolas; font-size: x-small;"><span style="color: #2b91af; font-family: Consolas; font-size: x-small;"><span style="color: #2b91af; font-family: Consolas; font-size: x-small;">EventArgs</span></span></span><span style="font-family: Consolas; font-size: x-small;"><span style="font-family: Consolas; font-size: x-small;"> e )</span></span><br />
<span style="font-family: Consolas; font-size: x-small;"><span style="font-family: Consolas; font-size: x-small;">{</span></span><span style="color: #2b91af; font-family: Consolas; font-size: x-small;"><span style="color: #2b91af; font-family: Consolas; font-size: x-small;"><span style="color: #2b91af; font-family: Consolas; font-size: x-small;"> </span></span></span><br />
<span style="color: #2b91af; font-family: Consolas; font-size: x-small;"> if( AccountController.OnlineUsers.Count > 0 )</span><br />
<span style="color: #2b91af; font-family: Consolas; font-size: x-small;"> {</span><br />
<span style="color: #2b91af; font-family: Consolas; font-size: x-small;"><span style="color: #2b91af; font-family: Consolas; font-size: x-small;"><span style="color: #2b91af; font-family: Consolas; font-size: x-small;"> LoggedInUsers</span></span></span><span style="font-family: Consolas; font-size: x-small;"><span style="font-family: Consolas; font-size: x-small;"> member </span></span><span style="color: #2b91af; font-family: Consolas; font-size: x-small;"><span style="color: #2b91af; font-family: Consolas; font-size: x-small;"><span style="color: #2b91af; font-family: Consolas; font-size: x-small;"> AccountController</span></span></span><span style="font-family: Consolas; font-size: x-small;"><span style="font-family: Consolas; font-size: x-small;">.OnlineUsers.Find( m => m.MemberName == </span></span><span style="color: #2b91af; font-family: Consolas; font-size: x-small;"><span style="color: #2b91af; font-family: Consolas; font-size: x-small;"><span style="color: #2b91af; font-family: Consolas; font-size: x-small;">HttpContext</span></span></span><span style="font-family: Consolas; font-size: x-small;"><span style="font-family: Consolas; font-size: x-small;">.Current.User.Identity.Name );</span></span><br />
<span style="color: blue; font-family: Consolas; font-size: x-small;"><span style="color: blue; font-family: Consolas; font-size: x-small;"><span style="color: blue; font-family: Consolas; font-size: x-small;"> if</span></span></span><span style="font-family: Consolas; font-size: x-small;"><span style="font-family: Consolas; font-size: x-small;">( member != </span></span><span style="color: blue; font-family: Consolas; font-size: x-small;"><span style="color: blue; font-family: Consolas; font-size: x-small;"><span style="color: blue; font-family: Consolas; font-size: x-small;">null</span></span></span><span style="font-family: Consolas; font-size: x-small;"><span style="font-family: Consolas; font-size: x-small;"> )</span></span><br />
<span style="font-family: Consolas; font-size: x-small;"> <span style="color: #2b91af;"><span style="color: #2b91af;"><span style="color: #2b91af;">AccountController</span></span></span>.OnlineUsers.Remove( member );<br /> }</span><br />
<span style="font-family: Consolas; font-size: x-small;">}</span><br />
<br />
We need to check here if the member is null because if a user logged out he/she will already be removed from the OnlineUsers list.<br />
<br />
Next you need to create a partial view method in your controller:<br />
<br />
public PartialViewResult OnlineUsers()<br />
<span style="font-family: Consolas; font-size: x-small;"><span style="font-family: Consolas; font-size: x-small;"><span style="font-family: Consolas; font-size: x-small;"><span style="font-family: Consolas; font-size: x-small;">{</span></span><br />
<span style="color: #2b91af; font-family: Consolas; font-size: x-small;"><span style="color: #2b91af; font-family: Consolas; font-size: x-small;"><span style="color: #2b91af; font-family: Consolas; font-size: x-small;"> List</span></span></span><span style="font-family: Consolas; font-size: x-small;"><span style="font-family: Consolas; font-size: x-small;"><</span></span><span style="color: #2b91af; font-family: Consolas; font-size: x-small;"><span style="color: #2b91af; font-family: Consolas; font-size: x-small;"><span style="color: #2b91af; font-family: Consolas; font-size: x-small;">LoggedInUsers</span></span></span><span style="font-family: Consolas; font-size: x-small;"><span style="font-family: Consolas; font-size: x-small;">> data = </span></span><span style="color: #2b91af; font-family: Consolas; font-size: x-small;"><span style="color: #2b91af; font-family: Consolas; font-size: x-small;"><span style="color: #2b91af; font-family: Consolas; font-size: x-small;">AccountController</span></span></span><span style="font-family: Consolas; font-size: x-small;"><span style="font-family: Consolas; font-size: x-small;">.OnlineUsers;</span></span></span></span><br />
<span style="font-family: Consolas; font-size: x-small;"><span style="font-family: Consolas; font-size: x-small;"><span style="color: blue; font-family: Consolas; font-size: x-small;"><span style="color: blue; font-family: Consolas; font-size: x-small;"><span style="color: blue; font-family: Consolas; font-size: x-small;"> return</span></span></span><span style="font-family: Consolas; font-size: x-small;"><span style="font-family: Consolas; font-size: x-small;"> PartialView( data );</span></span></span></span><br />
}<br />
<br />
Now you can create a partial view for logged in users to see:<br />
<br />
@model List<My_MSI.Net.Controllers.LoggedInUsers>
<br />
@foreach ( My_MSI.Net.Controllers.LoggedInUsers user in Model )<br />
<span style="font-family: Consolas; font-size: x-small;"><span style="font-family: Consolas; font-size: x-small;"><span style="font-family: Consolas; font-size: x-small;"><span style="font-family: Consolas; font-size: x-small;">{</span></span><br />
<span style="font-family: Consolas; font-size: x-small;"><span style="font-family: Consolas; font-size: x-small;">
@Html.Label( @Html.Lable( String.Format( "{0} logged in at {1}", user.MemberName, user.LoggedInTime.Tostring() ) )<br /><br />}</span></span></span></span><br />
<span style="font-family: Consolas; font-size: x-small;"><span style="font-family: Consolas; font-size: x-small;"><span style="font-family: Consolas; font-size: x-small;"><span style="font-family: Consolas; font-size: x-small;"></span></span></span></span><br />
<span style="font-family: Consolas; font-size: x-small;"><span style="font-family: Consolas; font-size: x-small;"><span style="font-family: Consolas; font-size: x-small;"><span style="font-family: Consolas; font-size: x-small;">Finally in your _Layout.cshtml file (You do have one of these, right?):</span></span><span style="font-family: Consolas; font-size: x-small;"><span style="font-family: Consolas; font-size: x-small;"><span style="color: blue; font-family: Consolas; font-size: x-small;"><span style="color: blue; font-family: Consolas; font-size: x-small;"><span style="color: blue; font-family: Consolas; font-size: x-small;"></span></span></span></span></span></span></span><br />
<span style="font-family: Consolas; font-size: x-small;"><span style="font-family: Consolas; font-size: x-small;"><span style="font-family: Consolas; font-size: x-small;"><span style="font-family: Consolas; font-size: x-small;"><span style="color: blue; font-family: Consolas; font-size: x-small;"><span style="color: blue; font-family: Consolas; font-size: x-small;"><span style="color: blue; font-family: Consolas; font-size: x-small;"><</span></span></span><span style="color: maroon; font-family: Consolas; font-size: x-small;"><span style="color: maroon; font-family: Consolas; font-size: x-small;"><span style="color: maroon; font-family: Consolas; font-size: x-small;">div</span></span></span><span style="font-family: Consolas; font-size: x-small;"><span style="font-family: Consolas; font-size: x-small;"> </span></span><span style="color: red; font-family: Consolas; font-size: x-small;"><span style="color: red; font-family: Consolas; font-size: x-small;"><span style="color: red; font-family: Consolas; font-size: x-small;">class</span></span></span><span style="color: blue; font-family: Consolas; font-size: x-small;"><span style="color: blue; font-family: Consolas; font-size: x-small;"><span style="color: blue; font-family: Consolas; font-size: x-small;">="move-right"></span></span></span></span></span></span></span><br />
<span style="font-family: Consolas; font-size: x-small;"><span style="font-family: Consolas; font-size: x-small;"><span style="font-family: Consolas; font-size: x-small;"><span style="font-family: Consolas; font-size: x-small;"><span style="font-family: Consolas; font-size: x-small;"><span style="font-family: Consolas; font-size: x-small;"> @{ Html.RenderAction( "OnlienUsers", "Your controllers name" ); }</span></span></span></span><br />
<span style="font-family: Consolas; font-size: x-small;"><span style="font-family: Consolas; font-size: x-small;"><span style="font-family: Consolas; font-size: x-small;"></span><span style="color: blue; font-family: Consolas; font-size: x-small;"><span style="color: blue; font-family: Consolas; font-size: x-small;"><span style="color: blue; font-family: Consolas; font-size: x-small;"></</span></span></span><span style="color: maroon; font-family: Consolas; font-size: x-small;"><span style="color: maroon; font-family: Consolas; font-size: x-small;"><span style="color: maroon; font-family: Consolas; font-size: x-small;">div</span></span></span><span style="color: blue; font-family: Consolas; font-size: x-small;"><span style="color: blue; font-family: Consolas; font-size: x-small;"><span style="color: blue; font-family: Consolas; font-size: x-small;">></span></span></span><br />
<br />
</span></span></span></span>Now you logged in users can see who else is logged in.<br />
<br />
If you want to show logged in users you'll have to create this View in your Home controller:<br />
<br />
<span style="font-family: Consolas; font-size: x-small;"><span style="font-family: Consolas; font-size: x-small;"></span></span><span style="color: blue; font-family: Consolas; font-size: x-small;"><span style="color: blue; font-family: Consolas; font-size: x-small;"><span style="color: blue; font-family: Consolas; font-size: x-small;">public</span></span></span><span style="font-family: Consolas; font-size: x-small;"><span style="font-family: Consolas; font-size: x-small;"> </span></span><span style="color: #2b91af; font-family: Consolas; font-size: x-small;"><span style="color: #2b91af; font-family: Consolas; font-size: x-small;"><span style="color: #2b91af; font-family: Consolas; font-size: x-small;">ActionResult</span></span></span><span style="font-family: Consolas; font-size: x-small;"><span style="font-family: Consolas; font-size: x-small;"> OnlineUsers()</span></span><br />
<span style="font-family: Consolas; font-size: x-small;"><span style="font-family: Consolas; font-size: x-small;">{</span></span><br />
<span style="color: #2b91af; font-family: Consolas; font-size: x-small;"><span style="color: #2b91af; font-family: Consolas; font-size: x-small;"><span style="color: #2b91af; font-family: Consolas; font-size: x-small;"> List</span></span></span><span style="font-family: Consolas; font-size: x-small;"><span style="font-family: Consolas; font-size: x-small;"><</span></span><span style="color: #2b91af; font-family: Consolas; font-size: x-small;"><span style="color: #2b91af; font-family: Consolas; font-size: x-small;"><span style="color: #2b91af; font-family: Consolas; font-size: x-small;">LoggedInUsers</span></span></span><span style="font-family: Consolas; font-size: x-small;"><span style="font-family: Consolas; font-size: x-small;">> data = </span></span><span style="color: #2b91af; font-family: Consolas; font-size: x-small;"><span style="color: #2b91af; font-family: Consolas; font-size: x-small;"><span style="color: #2b91af; font-family: Consolas; font-size: x-small;">AccountController</span></span></span><span style="font-family: Consolas; font-size: x-small;"><span style="font-family: Consolas; font-size: x-small;">.OnlineUsers;</span></span><br />
<span style="color: blue; font-family: Consolas; font-size: x-small;"><span style="color: blue; font-family: Consolas; font-size: x-small;"><span style="color: blue; font-family: Consolas; font-size: x-small;"> return</span></span></span><span style="font-family: Consolas; font-size: x-small;"><span style="font-family: Consolas; font-size: x-small;"> View( data );</span></span><br />
<span style="font-family: Consolas; font-size: x-small;"><span style="font-family: Consolas; font-size: x-small;">}</span></span><br />
<span style="font-family: Consolas; font-size: x-small;"><span style="font-family: Consolas; font-size: x-small;"></span></span><br />
<span style="font-family: Consolas; font-size: x-small;"><span style="font-family: Consolas; font-size: x-small;">And a View:</span></span><br />
<span style="font-family: Consolas; font-size: x-small;"><span style="font-family: Consolas; font-size: x-small;"></span></span><br />
<span style="font-family: Consolas; font-size: x-small;"><span style="font-family: Consolas; font-size: x-small;">@model List<My_MSI.Net.Controllers.LoggedInUser{@ViewBagTitle = "OnlineUsers";</span></span><span style="font-family: Consolas; font-size: x-small;"><span style="font-family: Consolas; font-size: x-small;">Layout = </span></span><span style="color: #a31515; font-family: Consolas; font-size: x-small;"><span style="color: #a31515; font-family: Consolas; font-size: x-small;"><span style="color: #a31515; font-family: Consolas; font-size: x-small;">"~/Views/Shared/_Layout.cshtml"</span></span></span><span style="font-family: Consolas; font-size: x-small;"><span style="font-family: Consolas; font-size: x-small;">;</span></span><span style="font-family: Consolas; font-size: x-small;"><span style="font-family: Consolas; font-size: x-small;">}</span></span><span style="color: maroon; font-family: Consolas; font-size: x-small;"><span style="color: maroon; font-family: Consolas; font-size: x-small;"><span style="color: maroon; font-family: Consolas; font-size: x-small;"><h2</span></span></span><span style="color: blue; font-family: Consolas; font-size: x-small;"><span style="color: blue; font-family: Consolas; font-size: x-small;"><span style="color: blue; font-family: Consolas; font-size: x-small;">></span></span></span><span style="font-family: Consolas; font-size: x-small;"><span style="font-family: Consolas; font-size: x-small;">OnlineUsers</h2></span></span><br />
<span style="font-family: Consolas; font-size: x-small;"></span><span style="font-family: Consolas; font-size: x-small;"><span style="font-family: Consolas; font-size: x-small;"></span></span><br />
<span style="color: blue; font-family: Consolas; font-size: x-small;"><span style="color: blue; font-family: Consolas; font-size: x-small;"><span style="color: blue; font-family: Consolas; font-size: x-small;">@foreach</span></span></span><span style="font-family: Consolas; font-size: x-small;"><span style="font-family: Consolas; font-size: x-small;"> ( My_MSI.Net.Controllers.</span></span><span style="color: #2b91af; font-family: Consolas; font-size: x-small;"><span style="color: #2b91af; font-family: Consolas; font-size: x-small;"><span style="color: #2b91af; font-family: Consolas; font-size: x-small;">LoggedInUsers</span></span></span><span style="font-family: Consolas; font-size: x-small;"><span style="font-family: Consolas; font-size: x-small;"> user </span></span><span style="color: blue; font-family: Consolas; font-size: x-small;"><span style="color: blue; font-family: Consolas; font-size: x-small;"><span style="color: blue; font-family: Consolas; font-size: x-small;">in</span></span></span><span style="font-family: Consolas; font-size: x-small;"><span style="font-family: Consolas; font-size: x-small;"> Model )</span></span><br />
<span style="font-family: Consolas; font-size: x-small;"><span style="font-family: Consolas; font-size: x-small;">
{</span></span><br />
<span style="font-family: Consolas; font-size: x-small;"><span style="font-family: Consolas; font-size: x-small;">
@Html.Label( String.Format "{0} logged in at {1}", user.MemberName, user.LoggedInTime.ToString() )<br /></span></span><br />
<span style="font-family: Consolas; font-size: x-small;">}</span><br />
<span style="font-family: Consolas; font-size: x-small;"><span style="font-family: Consolas; font-size: x-small;"></span></span><br />
<span style="font-family: Consolas; font-size: x-small;"><span style="font-family: Consolas; font-size: x-small;">Finally add a new menu item for Online Users and link it back to your OnlineUsers() method.</span></span><br />
<span style="font-family: Consolas; font-size: x-small;"><span style="font-family: Consolas; font-size: x-small;"></span></span><br />
<span style="font-family: Consolas; font-size: x-small;"><span style="font-family: Consolas; font-size: x-small;">That's it. You've successfully created a list of Online Users that Logged in members can see and a link were the general public can see who's logged in.</span></span><br />
<span style="font-family: Consolas; font-size: x-small;"><span style="font-family: Consolas; font-size: x-small;"></span></span><br />
<span style="font-family: Consolas; font-size: x-small;"><span style="font-family: Consolas; font-size: x-small;"> </span></span><br />
<span style="font-family: Consolas; font-size: x-small;"><span style="font-family: Consolas; font-size: x-small;"></span></span><span style="font-family: Consolas; font-size: x-small;"><span style="font-family: Consolas; font-size: x-small;"> </span></span><br />
<span style="font-family: Consolas; font-size: x-small;"><span style="font-family: Consolas; font-size: x-small;">
</span></span><br />
<br />
<br />Erichttp://www.blogger.com/profile/02676710416649644137noreply@blogger.com0tag:blogger.com,1999:blog-5617284324004521565.post-51593130875918806232012-12-16T17:19:00.004-08:002012-12-16T17:19:43.945-08:00How solve Unexpected Logout issuesWhen you set the Session TimeOut to 20, you would expect the Session to expire after 20 minutes of inactivity. However, you're using Session State Mode InProc (the default value), which means that the SessionState is stored in memory. When the Application Pool recycles. all Sessions stored in Memory will be lost. There can be many reasons why the Application Pool recycles.<br />
<br />
<a href="http://blogs.msdn.com/b/johan/archive/2007/05/16/common-reasons-why-your-application-pool-may-unexpectedly-recycle.aspx">http://blogs.msdn.com/b/johan/archive/2007/05/16/common-reasons-why-your-application-pool-may-unexpectedly-recycle.aspx</a><br />
<br />
Also, in a shared hosted environment, Application Pools recycles frequently. To overcome both problems, you should consider to use another SessionState Mode:<br />
<br />
<a href="http://msdn.microsoft.com/en-us/library/ms178586(v=vs.100).aspx">http://msdn.microsoft.com/en-us/library/ms178586(v=vs.100).aspx</a><br />
<br />
But this has nothing to do with authentication, as already stated! When you set the forms authentication to 20 minutes, it means that the user will be logged out anywhere between 10 to 20 minutes of inactivity. This is because the authentication ticket is only reset after more than half of the timeout has expired.<br />
<br />
<a href="http://msdn.microsoft.com/en-us/library/system.web.configuration.formsauthenticationconfiguration.slidingexpiration.aspx">http://msdn.microsoft.com/en-us/library/system.web.configuration.formsauthenticationconfiguration.slidingexpiration.aspx</a><br />
<br />
But sometimes the authentication ticket seems to expire unexpectedly also, forcing the user to the login page.. To understand why this happens, you need to understand how authentication works. <br />
<br />
When you login, an authentication ticket is created in a cookie. By default, this authentication ticket encrypted using the machinekey section in web.config. When this section is not specified in web.config, ASP.NET will generate one for you. If the application pool recycles, sometimes ASP.NET will generate a new machinekey (although MSDN says different!) especially in shared hosted environment. But with this new key, the authentication ticket cannot be decrypted anymore, so the user is redirected to the login page. To overcome this, simply add a machinekey section in your web.config, so the same key is used on each and every request:<br />
<br />
<a href="http://www.developmentnow.com/articles/machinekey_generator.aspx">http://www.developmentnow.com/articles/machinekey_generator.aspx</a>Erichttp://www.blogger.com/profile/02676710416649644137noreply@blogger.com0tag:blogger.com,1999:blog-5617284324004521565.post-92156583617796092482012-12-13T04:04:00.001-08:002012-12-13T04:04:26.981-08:00Ever had a View in MVC that was being reused by the Controller but the View doesn't display all the fields from the Model class?<br />
<br />
What doesn't work is creating another view to display the data. So don't waste your time trying to create another View!<br />
<br />
What does work is this:<br />
<br />
ModelState.Remove( "yourModel'sDataName" );<br />
<br />
You put the above statement (with your Model's Data Name) in the controller for every field that is not displaying even though you know that the Model class has data.<br />
<br />
. <br />
<br />
Erichttp://www.blogger.com/profile/02676710416649644137noreply@blogger.com0tag:blogger.com,1999:blog-5617284324004521565.post-17807957884075935582012-12-03T12:13:00.000-08:002012-12-12T13:33:08.191-08:00Ever wonder how to update a record with Entity Framework?<br />
<br />
Well, I'm about to show you how to do that with the controller:<br />
<br />
<span style="color: #2b91af; font-family: Consolas; font-size: x-small;"><span style="color: #2b91af; font-family: Consolas; font-size: x-small;"><span style="color: #2b91af; font-family: Consolas; font-size: x-small;">[HttpPost</span></span></span><span style="font-family: Consolas; font-size: x-small;"><span style="font-family: Consolas; font-size: x-small;">]</span></span><br />
<span style="color: blue; font-family: Consolas; font-size: x-small;"><span style="color: blue; font-family: Consolas; font-size: x-small;"><span style="color: blue; font-family: Consolas; font-size: x-small;">public</span></span></span><span style="font-family: Consolas; font-size: x-small;"><span style="font-family: Consolas; font-size: x-small;"> </span></span><span style="color: #2b91af; font-family: Consolas; font-size: x-small;"><span style="color: #2b91af; font-family: Consolas; font-size: x-small;"><span style="color: #2b91af; font-family: Consolas; font-size: x-small;">ActionResult</span></span></span><span style="font-family: Consolas; font-size: x-small;"><span style="font-family: Consolas; font-size: x-small;"> Manage( </span></span><span style="color: #2b91af; font-family: Consolas; font-size: x-small;"><span style="color: #2b91af; font-family: Consolas; font-size: x-small;"><span style="color: #2b91af; font-family: Consolas; font-size: x-small;">Home</span></span></span><span style="font-family: Consolas; font-size: x-small;"><span style="font-family: Consolas; font-size: x-small;"> data, </span></span><span style="color: blue; font-family: Consolas; font-size: x-small;"><span style="color: blue; font-family: Consolas; font-size: x-small;"><span style="color: blue; font-family: Consolas; font-size: x-small;">decimal</span></span></span><span style="font-family: Consolas; font-size: x-small;"><span style="font-family: Consolas; font-size: x-small;"> Id1, </span></span><span style="color: blue; font-family: Consolas; font-size: x-small;"><span style="color: blue; font-family: Consolas; font-size: x-small;"><span style="color: blue; font-family: Consolas; font-size: x-small;">decimal</span></span></span><span style="font-family: Consolas; font-size: x-small;"><span style="font-family: Consolas; font-size: x-small;"> Id2 )</span></span><span style="font-family: Consolas; font-size: x-small;"><span style="font-family: Consolas; font-size: x-small;">{<br /> data.MemberId.Id = Id1;<br /> data.MemberDetails.Id = Id2;</span></span><span style="color: #2b91af; font-family: Consolas; font-size: x-small;"><span style="color: #2b91af; font-family: Consolas; font-size: x-small;"><span style="color: #2b91af; font-family: Consolas; font-size: x-small;"> </span></span></span><br />
<span style="color: #2b91af; font-family: Consolas; font-size: x-small;"><span style="color: #2b91af; font-family: Consolas; font-size: x-small;"><span style="color: #2b91af; font-family: Consolas; font-size: x-small;"> Identity</span></span></span><span style="font-family: Consolas; font-size: x-small;"><span style="font-family: Consolas; font-size: x-small;"> record = db.Identity.FirstOrDefault( m => m.Id == Id1 );</span></span><br />
<span style="font-family: Consolas; font-size: x-small;"><span style="font-family: Consolas; font-size: x-small;"> record.Copy( data.MemberId );</span></span><br />
<span style="font-family: Consolas; font-size: x-small;"></span><span style="color: #2b91af; font-family: Consolas; font-size: x-small;"><span style="color: #2b91af; font-family: Consolas; font-size: x-small;"><span style="color: #2b91af; font-family: Consolas; font-size: x-small;"> Details</span></span></span><span style="font-family: Consolas; font-size: x-small;"><span style="font-family: Consolas; font-size: x-small;"> det = db.Details.FirstOrDefault( m => m.Id == Id2 );</span></span><br />
<span style="font-family: Consolas; font-size: x-small;"><span style="font-family: Consolas; font-size: x-small;"> det.Copy( data.MemberDetails );</span></span><br />
<span style="font-family: Consolas; font-size: x-small;"><span style="font-family: Consolas; font-size: x-small;"> ( (</span></span><span style="color: #2b91af; font-family: Consolas; font-size: x-small;"><span style="color: #2b91af; font-family: Consolas; font-size: x-small;"><span style="color: #2b91af; font-family: Consolas; font-size: x-small;">EFDbContext</span></span></span><span style="font-family: Consolas; font-size: x-small;"><span style="font-family: Consolas; font-size: x-small;">) db ).SaveChanges();</span></span><br />
<span style="font-family: Consolas; font-size: x-small;"><span style="font-family: Consolas; font-size: x-small;">
<br /> data.Status = </span></span><span style="font-family: Consolas; font-size: x-small;"><span style="font-family: Consolas; font-size: x-small;"><span style="color: #a31515; font-family: Consolas; font-size: x-small;"><span style="color: #a31515; font-family: Consolas; font-size: x-small;"><span style="color: #a31515; font-family: Consolas; font-size: x-small;">"Changes were sucessfully saved"</span></span></span><span style="font-family: Consolas; font-size: x-small;"><span style="font-family: Consolas; font-size: x-small;">;</span></span></span></span><span style="font-family: Consolas; font-size: x-small;"><span style="font-family: Consolas; font-size: x-small;">
</span></span><br />
<span style="font-family: Consolas; font-size: x-small;"></span><span style="color: blue; font-family: Consolas; font-size: x-small;"><span style="color: blue; font-family: Consolas; font-size: x-small;"><span style="color: blue; font-family: Consolas; font-size: x-small;"> return</span></span></span><span style="font-family: Consolas; font-size: x-small;"><span style="font-family: Consolas; font-size: x-small;"> View( data );</span></span><span style="font-family: Consolas; font-size: x-small;"><span style="font-family: Consolas; font-size: x-small;">}</span></span><br />
<span style="font-family: Consolas; font-size: x-small;"><span style="font-family: Consolas; font-size: x-small;">
<br />
What we are accomplishing here is this:<br />
<br />
The user has modified his/her Identity and/or Details records and we need to store them in the database.<br />
<br />
These records come back to us in a Home record that is simply a holder of several types needed by the home page of the site.<br />
<br />
The first thing we do is assign the record numbers to the two records because they are 0 when we get them in the controller.<br />
<br />
The next thing we do is read those records from the database again (that connection to the database was lost someplace between the [HttpGet] method that passes a Home record to the View).<br />
<br />
Then we call a copy method on the record to copy the updated info into the current record.<br />
<br />
We do those last two steps twice once for each record type.<br />
<br />
The next thing we do is call .SaveChanges() to write the updated info to the database.<br />
<br />
The next thing we do is provide a little feedback to the user in a [NotMapped] field on the Home class.<br />
<br />
Finally we return to the View passing the data we recieved.<br />
<br />
This is much easier than calling .SqlQuery( "Update..." ); especailly when the detail record has way too many members!<br />
<br />
<br />
</span></span>Erichttp://www.blogger.com/profile/02676710416649644137noreply@blogger.com0tag:blogger.com,1999:blog-5617284324004521565.post-86429175537629903542012-11-04T15:44:00.002-08:002013-01-01T12:45:54.984-08:00Ever seen a site that has a none movable side menu?<br />
<br />
It's easy to use with CSS:<br />
<br />
<pre>DIV.floating-menu
{
background: white;
float: left;
color: black;
padding: 10px 10px 10px 10px;
position: fixed;
text-align: center;
width: 200px;
z-index: 100;
}
</pre>
<br />
For IE 9 what works best is replacing: float: left; with: left: 0px; or if you want you menu on the right: right: 0px; works best in IE 9 because sometimes JavaScript or AJAX changes things that cause a Partial View to be missplaced.<br />
<br />
DIV.floating-menu a, DIV floating-menu h3
{
background: white;
color: Black;
font: Arial Bold;
margin: 0 0.5em;
text-align: center;
}
<br />
<br />
<cpde>Then in your HTML you just need to do something like this:</cpde><br />
<cpde></cpde><br />
<cpde><div class="floating-menu"></cpde><br />
<cpde><!--- your menu goes here --> </cpde><br />
<cpde></div></cpde><br />
<cpde></cpde><br />
<cpde>The key settings in the DIV.floating-menu CSS script are:</cpde><br />
<cpde></cpde><br />
<cpde>float: left;</cpde><br />
<cpde>position: fixed;</cpde><br />
<cpde>z-index: 100;</cpde><br />
<cpde></cpde><br />
<cpde>Again if using IE 9, replace: float: left; with left: 0px; or right: 0px because those work better with JavaScript and/or AJAX.</cpde><br />
<cpde></cpde><br />
<cpde>Any of the other setting is the DIV.floating-menu CSS script may be changed to anything you desire.</cpde><br />
<cpde></cpde><br />
<cpde></cpde><br />
<cpde> </cpde>Erichttp://www.blogger.com/profile/02676710416649644137noreply@blogger.com0tag:blogger.com,1999:blog-5617284324004521565.post-63187080455156455712012-03-09T05:39:00.000-08:002012-03-09T05:39:55.824-08:00What is My-MSI.Net?My-MSI.Net is a start-up company located in Falls Church, VA.<br />
<br />
What does My-MSI.Met do?<br />
<br />
My-MSI.Net writes Desktop applications for it's members to download from their Back Office web site.<br />
<br />
What do you need to run these Desktop Aplications?<br />
<br />
Nothing more than a Windows (XP or later) and an Internet connection.<br />
<br />
What technology do these Destop Applications use?<br />
<br />
We use Microsoft's .Net Framework and C#.<br />
<br />
What version of Microsoft's .Net is used?<br />
<br />
Currently we are using .Net version 4.0.<br />
<br />
What is the cost to join My-MSI.Net?<br />
<br />
Just $25.<br />
<br />
What is the subscription cost for My-MSI.Net?<br />
<br />
Just less than $0.90 per day, billed as $25 every 4 weeks*.<br />
<br />
What's the * mean?<br />
<br />
It means that we won't be starting the subscription fees until everyone on the 3rd level of the Matrix has 4 Members under them.<br />
<br />
Are there any positions on the 3rd level of the Matrix still available?<br />
<br />
Yes, we currently have 7 open positions on the 3rd level of the Matrix.<br />
<br />
Are there any other expenses involved with being a member of My-MSI.Net?<br />
<br />
Not for people on the 3rd level of the Matrix. For people on the 4th level (or higher) will need to promote their referral site. The expected cost of promoting a members referral site is $50 to $150 per month. All of the details will be available in the Back Office site.<br />
<br />
What form is the Matrix behind My-MSI.Net?<br />
<br />
My-MSI.Net uses a 4x5 Matrix, meaning that everyone has 4 people under them and they get paid 5 levels deep.<br />
<br />
What do members get paid?<br />
<br />
$6.25 from everyone on your first level (4 x $6.25 = $25) Reach this goal and your subscription fee no longer comes from your pocket!<br />
<br />
$1.25 from everyone on your second level (&1.25 x 16 = $20 in pure profit every 4 weeks.<br />
<br />
$1.50 from everyone on your third level ($1.50 x 64 = $96 + $20 = $116 every 4 weeks.<br />
<br />
$2.25 from everyone on your fourth level ($2.25 x 256 = $576 + $116 = $692 every 4 weeks.<br />
<br />
$3.00 from everyone on your fifth level ($3.00 x 1,024 = $3,072 + $692 = $3,764 every 4 weeks.<br />
<br />
Where does the rest of my $25 subscription fee go?<br />
<br />
$0.80 goes into the Bonus Pool, and $9.95 goes to pay for your referral site and your Back Office site. That $9.95 is closer to $9.00 by the time the Admin gets it because the Admin pays the transaction fees for all incoming funds.<br />
<br />
Does that mean that members pay a transaction fee to get their money out?<br />
<br />
Yes it does, but they will only be paying $5 on a $3,764 transaction.<br />
<br />
Who is developing the Desktop Applications? We have one Sr. .Net developer right now but plan to hire more as our member base grows.<br />
<br />
That's all you need to know about My.MSI.Net.Erichttp://www.blogger.com/profile/02676710416649644137noreply@blogger.com0tag:blogger.com,1999:blog-5617284324004521565.post-1001929401616730102012-02-23T04:53:00.000-08:002012-02-23T04:53:41.891-08:00What is Object Oriented programming?Object Oriented programming started back when C++ came out.<br />
<br />
The three tenents of Object Oriented programming are:<br />
<br />
Inheritance<br />
Encapsualtion<br />
Polymorphism<br />
<br />
Let's tackle these one at a time....<br />
<br />
<strong>Inheritance</strong><br />
<br />
Let's say you have a class called Vehicle and defined as:<br />
<br />
public class Vehicle<br />
{<br />
protected int wheels;<br />
protected int seats;<br />
protected int speed;<br />
protected float fuel;<br />
<br />
public Vehicle( int Wheels, int Seats, int Speed, float Fuel )<br />
{<br />
wheels = Wheels;<br />
seats = Seats;<br />
speed = Speed;<br />
fuel = Fuel;<br />
}<br />
public virtual void Drive();<br />
}<br />
<br />
Now let's say that you need a class called Car and another called Motorcycle:<br />
<br />
public class Car : Vehicle<br />
{<br />
public Car( int Seats, int Speed, float Fuel )<br />
{<br />
base.wheels = 4;<br />
base.seats = Seats;<br />
base.speed = Speed;<br />
base.fuel = Fuel;<br />
}<br />
<br />
public virtual void Drive()<br />
{<br />
// Drive the car<br />
}<br />
}<br />
<br />
public class Motorcycle : Vehicle<br />
{<br />
public Motorcycle( int Seats, int Speed, float Fuel )<br />
{<br />
base.wheels = 2;<br />
base.seats = Seats;<br />
base.speed = Speed;<br />
base.fuel = Fuel;<br />
}<br />
<br />
public virtual void Drive()<br />
{<br />
// Drive the Motorcycle<br />
}<br />
}<br />
<br />
Notice that the Car and the Motorcycle have no local storage, only the Vehicle has data members.<br />
<br />
Also notice the : Vehicle after Car and Motorcycle this indicates that Car and Motorcycle <strong>inherit</strong> from Vehicle.<br />
<br />
<strong>Encapsualation</strong><br />
<br />
Now let's say that you create a Radio class for entertainment.<br />
<br />
public class Radio<br />
{<br />
private float station;<br />
private float volume;<br />
private bool on;<br />
<br />
public void Tune( float Station )<br />
{<br />
station = Station;<br />
}<br />
<br />
public void VolumeUp( float amount )<br />
{<br />
volume += amount;<br />
}<br />
<br />
public void VolumeDown( float amount )<br />
{<br />
volume -= amount;<br />
}<br />
<br />
public void ToggleOnOff()<br />
{<br />
on = !on;<br />
}<br />
}<br />
<br />
Now you'd like to add the radio to the Car but you don't think it belongs in Vehicle.<br />
<br />
public class Car<br />
{<br />
private Radio radio = new Radio();<br />
<br />
public void Tune( float Station )<br />
{<br />
radio.Tune( Station );<br />
}<br />
<br />
public void VolumeUp( float amount )<br />
{<br />
radio.VolumeUp( amount );<br />
}<br />
<br />
public void RadioOnOff()<br />
{<br />
radio.ToggleOnOff();<br />
}<br />
<br />
// the rest of Car is as before<br />
}<br />
<br />
You could say that the Radio is <strong>encapsualated</strong> within the Car.<br />
<br />
<strong>Polymorphism</strong><br />
<br />
Let's say that you've created a Shape class as:<br />
<br />
public class Shape<br />
{<br />
public virtual float Area();<br />
public virtual void Draw();<br />
}<br />
<br />
Now you want to create some specific shapes:<br />
<br />
public class Circle : Shape<br />
{<br />
private int diameter;<br />
<br />
public Circle( int Diameter )<br />
{<br />
diameter = Diameter;<br />
}<br />
<br />
public virtual float Area()<br />
{<br />
// compute the Area of a circle<br />
return 0.0; // temp value until we actually compute the area<br />
}<br />
<br />
public virtual void Draw()<br />
{<br />
// draw the Circle<br />
}<br />
}<br />
<br />
public class Square : Shape<br />
{<br />
int side;<br />
<br />
public Square( int Side )<br />
{<br />
side = Side;<br />
}<br />
<br />
public virtual float Area()<br />
{<br />
return side * side;<br />
}<br />
<br />
public virtual void Draw()<br />
{<br />
// draw the Square<br />
}<br />
}<br />
<br />
Next you want to randomly create either a Circle or a Square:<br />
<br />
public class Factory<br />
{<br />
public Shape Create()<br />
{<br />
Shape shape = new Shape();<br />
Random r = new Random( DateTime.Now.Second );<br />
<br />
switch( r.Next( 0, 1 )<br />
{<br />
case 0:<br />
shape = new Circle( r.Next( 10 ) );<br />
break;<br />
case 1:<br />
shape = new Square( r.Next( 10 ) );<br />
break;<br />
}<br />
<br />
return shape;<br />
}<br />
}<br />
<br />
Next let's say that you want to create a loop that draw circles and squares without knowing which one you have:<br />
public DrawShapes()<br />
{ <br />
Factory f = new Factory();<br />
for( int i = 0; i < 10; ++i ) <br />
{<br />
Shape s = f.Create();<br />
s.Draw();<br />
}<br />
}<br />
<br />
What you just saw was an example of <strong>Polymorphism</strong>.<br />
<br />
Now that you understand the basics of Object Oriented programming, how do you go about designing your own classes?<br />
<br />
Classes are generally nouns or things. Notice our example classes were Vehicle, Car, Motorcyle, Shape, Circle and Square.<br />
Data within classes are generally either private or protected.<br />
Methods within Classes are generally verbs or actions. Notice that our methods were Drive, Area, Draw, etc.<br />
Methods are generally public but if you need a private helper method that's fine too.<br />
<br />
And that's about all you need to know about Object Oriented programming.Erichttp://www.blogger.com/profile/02676710416649644137noreply@blogger.com0tag:blogger.com,1999:blog-5617284324004521565.post-28848796930074399222012-02-21T05:47:00.000-08:002012-02-21T05:47:01.952-08:00What is this thing called C#?C# is a computer programming language based on C and C++. If you've ever learned either of those languages C# will fit like a glove.<br />
<br />
C# has all the operators of C and C++.<br />
<br />
C# does away with the header files used in C++.<br />
<br />
Like C and C++ every line of code in C# is terminated with a semicolon.<br />
<br />
A simple variable declaration looks like:<br />
<br />
string aString = "some string";<br />
<br />
A simple test looks like:<br />
<br />
if( aString == "some string" )<br />
{<br />
// do something usefull<br />
}<br />
<br />
A for loop looks like:<br />
<br />
for (int i = 0; i <= 10; ++i )<br />
{<br />
// do something usefull<br />
}<br />
<br />
If you have a collection of objects, like:<br />
<br />
List<string> aList = new List<string>();<br />
<br />
You can use a for each loop:<br />
<br />
for each( string str in aList )<br />
{<br />
// do something with str<br />
}<br />
<br />
If you have a loop of indeterminate length, you can do something like:<br />
<br />
bool flag = false;<br />
while( flag == false )<br />
{<br />
// do something usefull<br />
<br />
// when done simply:<br />
flag = true;<br />
}<br />
<br />
If you have a loop that needs to always go through a least 1 iteration, you can do something like:<br />
<br />
bool flag = false;<br />
do while ( flag == false )<br />
{<br />
// do somethig usefull<br />
<br />
// when done simply<br />
flag = true;<br />
}<br />
<br />
To define a namespace, you simply do this:<br />
<br />
namespace my.nameSpace<br />
{<br />
// whatever you want in that namespace<br />
}<br />
<br />
To define a class, you simply do this:<br />
<br />
public class myClass<br />
{<br />
// these are the class members<br />
private int anInt;<br />
private string aString;<br />
<br />
public myClass ( int i, string s ) // this is the class constructor, it initilizes the class members<br />
{<br />
anInt = i;<br />
aString = s;<br />
}<br />
<br />
public anAction()<br />
{<br />
// perform an action on the class members<br />
}<br />
<br />
public anotherAction()<br />
{<br />
// perform another action on the class members<br />
}<br />
}<br />
<br />
To use your newly defined class, you simply<br />
<br />
using my.nameSpace;<br />
<br />
myClass _myClass = new myClass( 1, "some string" );<br />
<br />
_myClass.anAction();<br />
_myClass.anotherAction();<br />
<br />
Of course the language of C# is not hard to learn and remember, the .Net framework is the challenging part of this equation. Your best on-line resource for the .Net framework is: <a href="http://msdn.microsoft.com/en-us/library">http://msdn.microsoft.com/en-us/library</a>Erichttp://www.blogger.com/profile/02676710416649644137noreply@blogger.com0tag:blogger.com,1999:blog-5617284324004521565.post-86131203766689827892012-02-11T14:33:00.001-08:002012-02-14T11:18:17.610-08:00How to create a MVC 3 web siteTo create a MVC application, you need to understand three things:<br />
1) The M in MVC stands for Model which is nothing more than a class within the Models namespace.<br />
2) The V in MVC stands for View which is the web page but it uses a different syntax call Razor <br />
which just means that you'll use a @ symbol at the front of the interesting parts.<br />
3) The C in MVC stands for Controller which is in the Controllers namespace and this replaces the code behind file in ASP.Net.<br />
<br />
Step 1: Open Visual Studio 2010 (which is the only version that supports MVC 3).<br />
You'll need to install some Essential Software:<br />
WebPI available at <a href="http://microsoft.com/web/downloads">http://microsoft.com/web/downloads</a> and click the download link. Download and run the installer. The name is a little confusing: this is the installer for the WebPI. The download is a regular Windows installer, which installs the WebPI tool. You'll use this tool to download and istall web application components.<br />
<br />
The WebPI will start automatically, and you will see the selection window.<br />
<br />
There are thrre categories aross the top of the screen. The components we are interested in are:<br />
<br />
Visual Studio 2010 SP1,<br />
ASP.NET MVC 3 Tools Update,<br />
SQL Server Express 2008 R2 (this one is optional since our application doesn't need a database).<br />
<br />
You will need at a minimum Windows XP Professional because IIS ships with only that version of Windows-XP. IIS ships with Windows-Vista and Windows-7 as well.<br />
<br />
Step 2: Create a new ASP.NET MVC 3 Web Appliction and call it HelloWorld_MVC<br />
Step 3: Select a Empty project template and select the Razor View Engine.<br />
Step 4: Create some special folders under your project: Content, Controllers, and Models<br />
Step 5: Right click on the Models folder and add a new Class called HelloWorldData.<br />
<br />
This is what your HelloWorldData class should look like:<br />
<br />
using System;<br />
namespace HelloWorld_MVC.Models<br />
{<br />
public class HelloWorldData<br />
{<br />
public Name { get; set; }<br />
public Greeting { get; set; }<br />
}<br />
}<br />
<br />
Step 6: Compile your project. This is very important because without compiling your project we won't be able to complete a future step.<br />
Step 7: Right click on the Controllers folder and add a new Controller class called <br />
HelloWorldController.<br />
<br />
This is what your HelloWorldController class should look like:<br />
<br />
using System;<br />
using System.Web;<br />
using System.Web.Mvc;<br />
using HellowWorld_MVC.Models;<br />
namespace HelloWorld_MVC.Controllers<br />
{<br />
public class HelloWorldController<br />
{<br />
public HelloWorldController()<br />
{<br />
}<br />
public ActionResult HelloWorld_MVC()<br />
{<br />
HelloWorldData data = new HelloWorldData();<br />
return View( data );<br />
}<br />
}<br />
}<br />
<br />
Step 8: Right-Click on View and select Add View from the pop-up menu.<br />
Step 9: The name is your method name by default, so we'll acept that.<br />
Step 10: Check the box for Create a strongly typed view and select the HelloWorldData from the <br />
dropdown list.<br />
Step 11: Uncheck the Use a layout or master page checkbox.<br />
<br />
Your web page should look something like:<br />
<br />
@model HelloWorld_MVC.Models.HelloWorldData<br />
@{<br />
ViewBag.Title = "Hello World MVC";<br />
}<br />
<h2>Hello World MVC</h2><br />
<div class="body"><br />
@using( Html.BeginForm())<br />
{<br />
@Html.EditorForModel()<br />
@Html.ActionLink( "Get Greeting", "HelloWorld_MVC", "HelloWorld" )<br />
}<br />
</div><br />
<br />
Step 11: This step is optional, but for instruction reasons, strongly recommended. Try running your site now and try clicking on the Get Greeting link. What happens? Don't worry right now, we're not done with our controller.<br />
Step 12: Modify your controller as follows:<br />
<br />
using System;<br />
using System.Text;<br />
using System.Web;<br />
using System.Web.Mvc;<br />
using HellowWorld_MVC.Models;<br />
namespace HelloWorld_MVC.Controllers<br />
{<br />
public class HelloWorldController<br />
{<br />
public HelloWorldController()<br />
{<br />
}<br />
[HttpGet]<br />
public ActionResult HelloWorld_MVC()<br />
{<br />
HelloWorldData data = new HelloWorldData();<br />
return View( data );<br />
}<br />
[HttpPost]<br />
public ActionResult HelloWorld_MVC( HelloWorldData data )<br />
{<br />
StringBuilder sb = new StringBuilder();<br />
sb.Append( "Hello " );<br />
if( data.Name.Length != 0 )<br />
sb.Append( data.Name );<br />
else<br />
sb.Append( "World" );<br />
data.Greeting = sb.ToString();<br />
return View( data );<br />
}<br />
}<br />
}<br />
Things to take note of:<br />
1) We added an using statement: using System.Text;<br />
2) We added a descriptor to our existing HelloWorld_MVC() function: [HttpGet]<br />
3) We added a new HelloWorld_MVC function that takes a HelloWorldData parameter and gave it the [HttpPost] descriptor.<br />
<br />
Step 13: Right-click on the View in the new method in your controller and select Go To View from the pop-up menu. if your previous View comes up, then that's great. If not, modify that View parameter list to include as the first parameter: "HelloWorld_MVC" as in View( "HelloWorld_MVC", data );<br />
<br />
Run your project again, and now the Get Greeting link will work as expected.<br />
<br />
Congradulations, you've sucessfully created your first ASP.Net MVC 3 site!Erichttp://www.blogger.com/profile/02676710416649644137noreply@blogger.com0tag:blogger.com,1999:blog-5617284324004521565.post-83477703004665374192012-02-10T18:11:00.000-08:002012-02-10T18:11:56.647-08:00How to create an ASP.Net web siteStep 1: Open Visual Studio<br />
Step 2: Create a new empty web forms project, name it: HelloWorld_Web<br />
Step 3: Add a new Web Form to the HelloWorld_Web project, named Default.aspx<br />
<br />
At this point, you should have a file that looks like:<br />
<br />
<pre><form id="form1" runat="server">
<div>
</div>
</form>
</pre><br />
Step 5: Switch over to Design mode (look at the bottom of your web page file)<br />
Step 6: Add a Label to the page, set it's text property to "What's Your Name"<br />
Step 7: Add a TextBox to the page, set it's Name property to txtName<br />
Step 8: Add a LinkButton to the page, set it's Name property to lnkGetGreeting<br />
Step 9: While on the property page for the LinkButton, go to the Events tab and double-click in the Click field. This will open up the code behind file and place an event handler in there. This is what the event handler code should look like:<br />
<br />
<br />
void lnkGetGreeting_Click( object sender, EventArgs args )<br />
{<br />
StringBuilder sb = new StringBuilder();<br />
<br />
sb.Append( "Hello " );<br />
<br />
if( txtName.Text.Length != 0 )<br />
<br />
sb.Append( txtName.Text )<br />
<br />
else<br />
<br />
sb.Append( "World" )<br />
<br />
<br />
lblGreeting.Text = sb.ToString();<br />
<br />
}<br />
<br />
<br />
Step 10: Go back to Default.aspx. Add a Label to the page, set it's Name proerty to lblGreeting.<br />
<br />
Run your page, click the GetGreeting link without entering a name, you should see "Hello World" appear in the lblGreeting Label. Next, enter your name in the first text field and click on the GetGreeting link again, you should see "Hello <your name>" this time.</span>Erichttp://www.blogger.com/profile/02676710416649644137noreply@blogger.com0tag:blogger.com,1999:blog-5617284324004521565.post-46164709309444801792012-02-09T09:27:00.000-08:002012-02-09T09:51:52.502-08:00How to create a simple WinForms Project?Step 1: Start up Visual Studio.<br />
Step 2: Create a new Windows Forms project called HelloWorld.<br />
Step 3: Drag a Label control onto the Form and set it's Text property to "What's Your Name:'.<br />
Step 4: Drag a TextBox control onto the Form and name it txtName.<br />
Step 5: Drag a Label control onto the form, clear it's Text property and name lblGreeting.<br />
Step 6: Drag a Button control onto the form and name it btnExit.<br />
Step 7: Drag a Button control onto the form and name it btnGreeting.<br />
Step 8: Right click away from the Form and select View Code from the pop-up menu.<br />
<br />
When you first created the Windows Forms project, Visual Studio started you off with a blank form called Form1 and created this program.cs file:<br />
<br />
<pre style="background: silver; color: black; font-family: Consolas; font-size: 13px;"><span style="color: blue;">using</span> System;
<span style="color: blue;">using</span> System.Windows.Forms;
<span style="color: blue;">namespace</span> HelloWorld
{
<span style="color: blue;">static</span> <span style="color: blue;">class</span> <span style="color: #2b91af;">Program</span>
{
<span style="color: grey;">///</span><span style="color: green;"> </span><span style="color: grey;"><summary></span>
<span style="color: grey;">///</span><span style="color: green;"> The main entry point for the application.</span>
<span style="color: grey;">///</span><span style="color: green;"> </span><span style="color: grey;"></summary></span>
[<span style="color: #2b91af;">STAThread</span>]
<span style="color: blue;">static</span> <span style="color: blue;">void</span> Main()
{
<span style="color: #2b91af;">Application</span>.EnableVisualStyles();
<span style="color: #2b91af;">Application</span>.SetCompatibleTextRenderingDefault( <span style="color: blue;">false</span> );
<span style="color: #2b91af;">Application</span>.Run( <span style="color: blue;">new</span> <span style="color: #2b91af;">Form1</span>() );
}
}
}
</pre>When you selected View Code from the pop-up menu you got something like this:<br />
<br />
<pre style="background: silver; color: black; font-family: Consolas; font-size: 13px;"><span style="color: blue;">using</span> System;
<span style="color: blue;">using</span> System.Text;
<span style="color: blue;">using</span> System.Windows.Forms;
<span style="color: blue;">namespace</span> HelloWorld
{
<span style="color: blue;">public</span> <span style="color: blue;">partial</span> <span style="color: blue;">class</span> <span style="color: #2b91af;">Form1</span> : <span style="color: #2b91af;">Form</span>
{
<span style="color: blue;">public</span> Form1()
{
InitializeComponent();
}
}
}
</pre>Notice the using System.Text; line at the top of the form1.cs file, that is the namespace that includes the StringBuilder class that we are using.<br />
<br />
With just that much code, if you run the form, it will resize, minimize, and close with the close button, but the btnExit and btnGreeting buttons will accomplish nothing yet.<br />
<br />
To make the btnExit accomplish what it should be doing, add this to your Form1 class<br />
<br />
<pre style="background: silver; color: black; font-family: Consolas; font-size: 13px;"> <span style="color: blue;">private</span> <span style="color: blue;">void</span> btnExit_Click( <span style="color: blue;">object</span> sender, <span style="color: #2b91af;">EventArgs</span> e )
{
<span style="color: #2b91af;">Application</span>.Exit();
}
</pre><br />
To make the btnGreeting accomplish what it should be doing, add this to your Form1 class:<br />
<br />
<pre style="background: silver; color: black; font-family: Consolas; font-size: 13px;"> <span style="color: blue;">private</span> <span style="color: blue;">void</span> btnGreeting_Click( <span style="color: blue;">object</span> sender, <span style="color: #2b91af;">EventArgs</span> e )
{
<span style="color: #2b91af;">StringBuilder</span> sb = <span style="color: blue;">new</span> <span style="color: #2b91af;">StringBuilder</span>();
sb.Append( <span style="color: #a31515;">"Hello "</span> );
<span style="color: blue;">if</span> ( txtName.Text.Length != 0 )
sb.Append( txtName.Text );
<span style="color: blue;">else</span>
sb.Append( <span style="color: #a31515;">"World"</span> );
lblGreeting.Text = sb.ToString();
}
</pre><br />
Now you can run the form again.<br />
<br />
Try hitting the Get Greeting button without entering anything in the Text Box.<br />
<br />
You should see that the lblGreeting was set to "Hello World".<br />
<br />
Try putting your name into the Text Box and then hit the Get Greeting button again.<br />
<br />
This time you should see "Hello <your name>"<br />
<br />
Now, let's talk about what the btnGreeting_Click method was actually doing:<br />
<br />
Since we are building a two part string, we used a StringBuilder class and named it sb. If we had left it at that we would have had a null object since all classes are objects. So that's why sb = new StringBuilder();<br />
<br />
The next thing we do is sb.Append( "Hello " ); This appends the word "Hello" followed by a space to our empty sb.<br />
<br />
What comes next is a test on the length of the string entered into the Text Box.<br />
<br />
if( txtName.Text.Lenght != 0 )<br />
<br />
If this condition is true, we append the txtName.Text onto our sb, with <br />
sb.Append( txtName.Text);<br />
<br />
If this condition is false, we append "World" onto our sb, with sb.Append( "World" );<br />
<br />
Finally, we set the lblGreeting's Text property to the contents of our sb, with<br />
lblGreeting.Text = sb.ToString();<br />
<br />
Now we'll talk a little about the btnExit_Click method:<br />
<br />
This event handler only has one thing to do, cause the application to exit. To accomplish this task, we use the Application class that is part of the Form class that our Form1 class inhereted from. Application.Exit();<br />
<br />
There is only one more addition to make to make our form's title bar say "Hello World" instead of "Form1":<br />
<br />
In the Form1 constructor, public Form1() after the call to InitializeComponent() add this line:<br />
Text = "Hello World";<br />
<br />
Congradulations, you've now created your first Windows Forms project!<br />
<br />
But what was that program.cs file doing? In every Windows Forms project there has to be a starting place, and that starting place is a static method called Main in a class called Program. Now the class called Program is enclosed within a namespace called HelloWorld.<br />
<br />
Up above the namespace and class we have two necessary using statements;<br />
using System;<br />
using System.Windows.Forms;<br />
<br />
These pull in the namespaces needed by our HelloWorld project.<br />
<br />
The next two lines just set up some default actions on the Appliction class. It's the third line that very important for our purposes:<br />
Application.Run( new Form1() );<br />
<br />
When we say new Form1() we are getting a new instance of the class Form1. So this third line is telling the Appliction to Run a new Form1(); Which calls the constructor Form1() which calls InitializeCompentent(); which puts all of our controls on the form.<br />
<br />
And now you understand how a Windows Forms project gets started.Erichttp://www.blogger.com/profile/02676710416649644137noreply@blogger.com0tag:blogger.com,1999:blog-5617284324004521565.post-25824257063961060442012-02-06T13:58:00.000-08:002012-11-25T14:42:28.286-08:00Implementing HTTP File Upload with ASP.NET MVC<a href="http://www.blogger.com/" name="abc137b6b-d8d0-47d1-9795-f8814f7d1903"></a><br />
<div class="item">
<h2>
Implementing HTTP File Upload with ASP.NET MVC including Tests and Mocks </h2>
<div class="item-content">
A number of folks have asked me how to "implement the ASP.NET File Upload Control" except using ASP.NET MVC. This is a really interesting question for a number of reasons and a great opportunity to explore some fundamentals.<br />
<br />
First, ASP.NET MVC is different since we don't get to use ASP.NET Server Controls as we're used to them. There's no "server controls" in the way that we're used to them. <br />
<br />
Second, it'd be important to write Unit Tests for something like File Upload, and since ASP.NET MVC tries to be Unit Test friendly, it's an interesting problem to do tests. Why is it interesting? Well, ASP.NET MVC <strong>sits on top of </strong>ASP.NET. That means ASP.NET MVC didn't do any special work for File Upload support. It uses whatever stuff is built into ASP.NET itself. This may or not be helpful or interesting or even easy to test.<br />
<br />
It seems then, that this is a good exercise in understanding a number of things:<br />
<ul>
<li>HTTP and How File Upload works via HTTP </li>
<li>What ASP.NET offers for to catch File Uploads </li>
<li>How to Mock things that aren't really Mock Friendly </li>
<li>And ultimately, How to do File Upload with ASP.NET MVC </li>
</ul>
Here we go.<br />
<h3>
HTTP and How File Upload works via HTTP</h3>
It's always better, for me, to understand WHY and HOW something is happening. If you say "just because" or "whatever, you just add that, and it works" then I think that's sad. For some reason while many folks understand FORM POSTs and generally how form data is passed up to the server, when a file is transferred many just conclude it's magic.<br />
<br />
Why do we <em>have </em>to add <span style="font-family: Courier New; font-size: x-small;">enctype="multipart/form=data"</span> on our forms that include file uploads? Because the form will now be POSTed in <em>multiple parts.</em><br />
If you have a form like this:<br />
<div>
<div class="syntaxhighlighter html ie" id="highlighter_700871">
<div class="toolbar">
</div>
<table border="0" cellpadding="0" cellspacing="0"><tbody>
<tr><td class="gutter"><div class="line number1 index0 alt2">
1</div>
<div class="line number2 index1 alt1">
2</div>
<div class="line number3 index2 alt2">
3</div>
<div class="line number4 index3 alt1">
4</div>
<div class="line number5 index4 alt2">
5</div>
<div class="line number6 index5 alt1">
6</div>
<div class="line number7 index6 alt2">
7</div>
</td><td class="code"><div class="container">
<div class="line number1 index0 alt2">
<code class="html plain"><</code><code class="html keyword">form</code> <code class="html color1">action</code><code class="html plain">=</code><code class="html string">"/home/uploadfiles"</code> <code class="html color1">method</code><code class="html plain">=</code><code class="html string">"post"</code> <code class="html color1">enctype</code><code class="html plain">=</code><code class="html string">"multipart/form-data"</code><code class="html plain">></code></div>
<div class="line number2 index1 alt1">
<code class="html spaces"> </code><code class="html plain"><</code><code class="html keyword">label</code> <code class="html color1">for</code><code class="html plain">=</code><code class="html string">"file"</code><code class="html plain">>Filename:</</code><code class="html keyword">label</code><code class="html plain">></code></div>
<div class="line number3 index2 alt2">
<code class="html spaces"> </code><code class="html plain"><</code><code class="html keyword">input</code> <code class="html color1">type</code><code class="html plain">=</code><code class="html string">"file"</code> <code class="html color1">name</code><code class="html plain">=</code><code class="html string">"file"</code> <code class="html color1">id</code><code class="html plain">=</code><code class="html string">"file"</code> <code class="html plain">/></code></div>
<div class="line number4 index3 alt1">
</div>
<div class="line number5 index4 alt2">
<code class="html spaces"> </code><code class="html plain"><</code><code class="html keyword">input</code> <code class="html color1">type</code><code class="html plain">=</code><code class="html string">"submit"</code> <code class="html color1">name</code><code class="html plain">=</code><code class="html string">"submit"</code> <code class="html color1">value</code><code class="html plain">=</code><code class="html string">"Submit"</code> <code class="html plain">/></code></div>
<div class="line number6 index5 alt1">
<code class="html plain"></</code><code class="html keyword">form</code><code class="html plain">></code></div>
<div class="line number6 index5 alt1">
</div>
<div class="line number6 index5 alt1">
</div>
</div>
</td></tr>
</tbody></table>
</div>
</div>
The resulting Form POST will look like this (slightly simplified):<br />
<pre>POST /home/uploadfiles HTTP/1.1
Content-Type: multipart/form-data; boundary=---------------------------7d81b516112482
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0; WOW64)
Content-Length: 324
-----------------------------7d81b516112482
Content-Disposition: form-data; name="file"; filename="\\SERVER\Users\Scott\Documents\test.txt"
Content-Type: text/plain
foo
-----------------------------7d81b516112482
Content-Disposition: form-data; name="submit"
Submit
-----------------------------7d81b516112482--</pre>
<pre>Notice a few things about this POST. First, notice the content-type and boundary="" and how the boundary is used later, as exactly that, a boundary between the multiple parts. See how the first part shows that I uploaded a single file, of type text/plain. You can interpolate from this how you'd expect multiple files to show up if they were all POSTed at once.</pre>
<br />
And of course, look at how different this would look if it were just a basic form POST without the enctype="multipart/form=data" included:<br />
<pre> </pre>
<pre>POST /home/uploadfiles HTTP/1.1
Content-Type: application/x-www-form-urlencoded
UA-CPU: x86
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0; WOW64)
Content-Length: 13
submit=Submit</pre>
<br />
See how the content type is different? This is a regular, typical form POST. Perhaps atypical in that it includes only a Submit button!<br />
<br />
The point is, when folks add a ASP.NET FileUpload Control to their designer, it's useful to remember that you're buying into an abstraction over something. In this case, you're using a control that promises to hide the whole multipart MIME way of looking at things, and that's totally cool. <br />
<blockquote>
<strong>Back To Basics Tip <br />
<em>Know </em>what <em>your library is hiding from you and </em>why <em>you chose it.</em></strong></blockquote>
As an aside, if you looked at an email of yours with multiple attached files, it would look VERY similar to the body of the first HTTP message as multipart MIME encoding is found everywhere, as is common with most good ideas.<br />
<h3>
What ASP.NET offers for to catch File Uploads</h3>
The FileUpload control is just a control that sits on top of a bunch of support for FileUploads in ASP.NET, starting with the classes Request.Files and HttpPostedFile. Those are the things that actually do the hold on to the parsed Files from an HTTP Request. You can use them to get a hold of a stream (a bunch of bytes in memory that are the file) or just save the file.<br />
<br />
Since we can't use ASP.NET Server Controls in ASP.NET MVC, we'll use these classes instead. Here's how you usually grab all the files from an upload and save them:<br />
<div>
<div class="syntaxhighlighter c# ie" id="highlighter_769764">
<div class="toolbar">
</div>
<table border="0" cellpadding="0" cellspacing="0"><tbody>
<tr><td class="gutter"><div class="line number1 index0 alt2">
1</div>
<div class="line number2 index1 alt1">
2</div>
<div class="line number3 index2 alt2">
3</div>
<div class="line number4 index3 alt1">
4</div>
<div class="line number5 index4 alt2">
5</div>
<div class="line number6 index5 alt1">
6</div>
<div class="line number7 index6 alt2">
7</div>
<div class="line number8 index7 alt1">
8</div>
<div class="line number9 index8 alt2">
9</div>
<div class="line number10 index9 alt1">
10</div>
</td><td class="code"><div class="container">
<div class="line number1 index0 alt2">
<code class="c# keyword">foreach</code> <code class="c# plain">(</code><code class="c# keyword">string</code> <code class="c# plain">file </code><code class="c# keyword">in</code> <code class="c# plain">Request.Files)</code></div>
<div class="line number2 index1 alt1">
<code class="c# plain">{</code></div>
<div class="line number3 index2 alt2">
<code class="c# spaces"> </code><code class="c# plain">HttpPostedFile hpf = Request.Files[file] </code><code class="c# keyword">as</code> <code class="c# plain">HttpPostedFile;</code></div>
<div class="line number4 index3 alt1">
<code class="c# spaces"> </code><code class="c# keyword">if</code> <code class="c# plain">(hpf.ContentLength == 0)</code></div>
<div class="line number5 index4 alt2">
<code class="c# spaces"> </code><code class="c# keyword">continue</code><code class="c# plain">;</code></div>
<div class="line number6 index5 alt1">
<code class="c# spaces"> </code><code class="c# keyword">string</code> <code class="c# plain">savedFileName = Path.Combine(</code></div>
<div class="line number7 index6 alt2">
<code class="c# spaces"> </code><code class="c# plain">AppDomain.CurrentDomain.BaseDirectory, </code></div>
<div class="line number8 index7 alt1">
<code class="c# spaces"> </code><code class="c# plain">Path.GetFileName(hpf.FileName));</code></div>
<div class="line number9 index8 alt2">
<code class="c# spaces"> </code><code class="c# plain">hpf.SaveAs(savedFileName);</code></div>
<div class="line number10 index9 alt1">
<code class="c# plain">}</code></div>
<div class="line number10 index9 alt1">
</div>
<div class="line number10 index9 alt1">
</div>
</div>
</td></tr>
</tbody></table>
</div>
</div>
Of course, you might want to change the directory and filename, maybe check the mimeType to allow only certain kinds of files, or check the length to limit your uploads, but this is the general idea. <br />
<br />
Note that Request.Files has been around since 1.x and isn't a strongly typed collection of anything, so the GetEnumerator() of .Files that we're using in the foreach returns strings that are then used as keys into the Files[] indexer. It's a little wonky as it's old.<br />
<br />
However, don't let me get ahead of myself, let's write the tests first!<br />
<h3>
How to Mock things that aren't really Mock Friendly </h3>
After creating a new ASP.NET MVC Project and making sure to select a test framework, I'll drop into a Controller Test and make a new TestMethod that kind of looks like I expect my method to be used.<br />
<div>
<div class="syntaxhighlighter c# ie" id="highlighter_458241">
<div class="toolbar">
?</div>
<table border="0" cellpadding="0" cellspacing="0"><tbody>
<tr><td class="gutter"><div class="line number1 index0 alt2">
1</div>
<div class="line number2 index1 alt1">
2</div>
<div class="line number3 index2 alt2">
3</div>
<div class="line number4 index3 alt1">
4</div>
<div class="line number5 index4 alt2">
5</div>
<div class="line number6 index5 alt1">
6</div>
<div class="line number7 index6 alt2">
7</div>
<div class="line number8 index7 alt1">
8</div>
<div class="line number9 index8 alt2">
9</div>
<div class="line number10 index9 alt1">
10</div>
<div class="line number11 index10 alt2">
11</div>
</td><td class="code"><div class="container">
<div class="line number1 index0 alt2">
<code class="c# plain">[TestMethod]</code></div>
<div class="line number2 index1 alt1">
<code class="c# keyword">public</code> <code class="c# keyword">void</code> <code class="c# plain">FakeUploadFiles()</code></div>
<div class="line number3 index2 alt2">
<code class="c# plain">{</code></div>
<div class="line number4 index3 alt1">
<code class="c# spaces"> </code><code class="c# plain">HomeController controller = </code><code class="c# keyword">new</code> <code class="c# plain">HomeController();</code></div>
<div class="line number5 index4 alt2">
</div>
<div class="line number6 index5 alt1">
<code class="c# spaces"> </code><code class="c# plain">ViewResult result = controller.UploadFiles() </code><code class="c# keyword">as</code> <code class="c# plain">ViewResult;</code></div>
<div class="line number7 index6 alt2">
<code class="c# spaces"> </code><code class="c# plain">var uploadedResult = result.ViewData.Model </code><code class="c# keyword">as</code> <code class="c# plain">List<ViewDataUploadFilesResult>;</code></div>
<div class="line number8 index7 alt1">
<code class="c# spaces"> </code><code class="c# plain">Assert.AreEqual(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, </code><code class="c# string">"foo.doc"</code><code class="c# plain">), uploadedResult[0].Name);</code></div>
<div class="line number9 index8 alt2">
<code class="c# spaces"> </code><code class="c# plain">Assert.AreEqual(8192, uploadedResult[0].Length);</code></div>
<div class="line number10 index9 alt1">
<code class="c# plain">}</code></div>
<div class="line number10 index9 alt1">
</div>
<div class="line number10 index9 alt1">
</div>
</div>
</td></tr>
</tbody></table>
</div>
</div>
This is incomplete, though, as I'm writing the tests before I the implementation exists. I need to think about how this should be implemented, and as I learn what should be mocked, I need to go back and forth between the tests and the implementation. <br />
<br />
If we tried to compile this test, it won't, until I add a few types and methods. Once it actually compiles, but before I write the method itself, I'll want to see it FAIL. If you get a test to PASS on the first try, you don't really know yet if it CAN fail. Making it fail first proves that it's broken. Then you get to fix it. <br />
<blockquote>
<strong>Back To Basics Tip <br />
<em>Remember, in TDD, if it ain't broke, you don't get to fix it.</em></strong></blockquote>
<img alt="image" border="0" height="187" src="http://www.hanselman.com/blog/content/binary/WindowsLiveWriter/ImplementingHTTPFil.NETMVCincludingTests_E4A1/image_3.png" style="border-width: 0px; margin: 10px 0px;" width="657" /> <br />
There's a bit of a chicken and the egg because it's unclear what will need to be mocked out until I start the implementation. However, this draft method above generally says what I want to do. I want to my controller to have a method called UploadFiles() that will grab the uploaded files from Request.Files, save them, then put a type in the ViewData saying which files were saved and how large they were.<br />
<br />
Ok, take a breath. The following code may look freaky, but it's really cool actually. You can use any <a href="http://www.mockframeworks.com/">Mock Framework</a> you like, but I like <a href="http://www.mockframeworks.com/moq">Moq</a> for it's fluency. <br />
<br />
We're having to "mock" things because we need to <em>lie </em>to our controller, who's expecting an HTTP Post, remember? It's going to go and spin through Request.Files and try to save each file. Since we want to test this <em>without the web server or web browser, </em>we'll want to tell the Moq framework<em> </em>about our expectations. <br />
<blockquote>
<strong>Back To Basics Tip <br />
<em>Be careful to mock context and assert outputs but don't mock away the whole test!</em></strong></blockquote>
I've commented the code to explain...<br />
<div>
<div class="syntaxhighlighter c# ie" id="highlighter_984665">
<div class="toolbar">
?</div>
<table border="0" cellpadding="0" cellspacing="0"><tbody>
<tr><td class="gutter"><div class="line number1 index0 alt2">
1</div>
<div class="line number2 index1 alt1">
2</div>
<div class="line number3 index2 alt2">
3</div>
<div class="line number4 index3 alt1">
4</div>
<div class="line number5 index4 alt2">
5</div>
<div class="line number6 index5 alt1">
6</div>
<div class="line number7 index6 alt2">
7</div>
<div class="line number8 index7 alt1">
8</div>
<div class="line number9 index8 alt2">
9</div>
<div class="line number10 index9 alt1">
10</div>
<div class="line number11 index10 alt2">
11</div>
<div class="line number12 index11 alt1">
12</div>
<div class="line number13 index12 alt2">
13</div>
<div class="line number14 index13 alt1">
14</div>
<div class="line number15 index14 alt2">
15</div>
<div class="line number16 index15 alt1">
16</div>
<div class="line number17 index16 alt2">
17</div>
<div class="line number18 index17 alt1">
18</div>
<div class="line number19 index18 alt2">
19</div>
<div class="line number20 index19 alt1">
20</div>
<div class="line number21 index20 alt2">
21</div>
<div class="line number22 index21 alt1">
22</div>
<div class="line number23 index22 alt2">
23</div>
<div class="line number24 index23 alt1">
24</div>
<div class="line number25 index24 alt2">
25</div>
<div class="line number26 index25 alt1">
26</div>
<div class="line number27 index26 alt2">
27</div>
<div class="line number28 index27 alt1">
28</div>
<div class="line number29 index28 alt2">
29</div>
<div class="line number30 index29 alt1">
30</div>
<div class="line number31 index30 alt2">
31</div>
<div class="line number32 index31 alt1">
32</div>
<div class="line number33 index32 alt2">
33</div>
<div class="line number34 index33 alt1">
34</div>
<div class="line number35 index34 alt2">
35</div>
<div class="line number36 index35 alt1">
36</div>
<div class="line number37 index36 alt2">
37</div>
<div class="line number38 index37 alt1">
38</div>
<div class="line number39 index38 alt2">
39</div>
<div class="line number40 index39 alt1">
40</div>
<div class="line number41 index40 alt2">
41</div>
<div class="line number42 index41 alt1">
42</div>
<div class="line number43 index42 alt2">
43</div>
<div class="line number44 index43 alt1">
44</div>
</td><td class="code"><div class="container">
<div class="line number1 index0 alt2">
<code class="c# plain">[TestMethod]</code></div>
<div class="line number2 index1 alt1">
<code class="c# keyword">public</code> <code class="c# keyword">void</code> <code class="c# plain">FakeUploadFiles()</code></div>
<div class="line number3 index2 alt2">
<code class="c# plain">{</code></div>
<div class="line number4 index3 alt1">
<code class="c# spaces"> </code><code class="c# comments">//We'll need mocks (fake) of Context, Request and a fake PostedFile</code></div>
<div class="line number5 index4 alt2">
<code class="c# spaces"> </code><code class="c# plain">var request = </code><code class="c# keyword">new</code> <code class="c# plain">Mock<HttpRequestBase>();</code></div>
<div class="line number6 index5 alt1">
<code class="c# spaces"> </code><code class="c# plain">var context = </code><code class="c# keyword">new</code> <code class="c# plain">Mock<HttpContextBase>();</code></div>
<div class="line number7 index6 alt2">
<code class="c# spaces"> </code><code class="c# plain">var postedfile = </code><code class="c# keyword">new</code> <code class="c# plain">Mock<HttpPostedFileBase>();</code></div>
<div class="line number8 index7 alt1">
</div>
<div class="line number9 index8 alt2">
<code class="c# spaces"> </code><code class="c# comments">//Someone is going to ask for Request.File and we'll need a mock (fake) of that.</code></div>
<div class="line number10 index9 alt1">
<code class="c# spaces"> </code><code class="c# plain">var postedfilesKeyCollection = </code><code class="c# keyword">new</code> <code class="c# plain">Mock<HttpFileCollectionBase>();</code></div>
<div class="line number11 index10 alt2">
<code class="c# spaces"> </code><code class="c# plain">var fakeFileKeys = </code><code class="c# keyword">new</code> <code class="c# plain">List<</code><code class="c# keyword">string</code><code class="c# plain">>() { </code><code class="c# string">"file"</code> <code class="c# plain">};</code></div>
<div class="line number12 index11 alt1">
</div>
<div class="line number13 index12 alt2">
<code class="c# spaces"> </code><code class="c# comments">//OK, Mock Framework! Expect if someone asks for .Request, you should return the Mock!</code></div>
<div class="line number14 index13 alt1">
<code class="c# spaces"> </code><code class="c# plain">context.Expect(ctx => ctx.Request).Returns(request.Object);</code></div>
<div class="line number15 index14 alt2">
<code class="c# spaces"> </code><code class="c# comments">//OK, Mock Framework! Expect if someone asks for .Files, you should return the Mock with fake keys!</code></div>
<div class="line number16 index15 alt1">
<code class="c# spaces"> </code><code class="c# plain">request.Expect(req => req.Files).Returns(postedfilesKeyCollection.Object);</code></div>
<div class="line number17 index16 alt2">
<code class="c# spaces"> </code> </div>
<div class="line number18 index17 alt1">
<code class="c# spaces"> </code><code class="c# comments">//OK, Mock Framework! Expect if someone starts foreach'ing their way over .Files, give them the fake strings instead!</code></div>
<div class="line number19 index18 alt2">
<code class="c# spaces"> </code><code class="c# plain">postedfilesKeyCollection.Expect(keys => keys.GetEnumerator()).Returns(fakeFileKeys.GetEnumerator());</code></div>
<div class="line number20 index19 alt1">
</div>
<div class="line number21 index20 alt2">
<code class="c# spaces"> </code><code class="c# comments">//OK, Mock Framework! Expect if someone asks for file you give them the fake!</code></div>
<div class="line number22 index21 alt1">
<code class="c# spaces"> </code><code class="c# plain">postedfilesKeyCollection.Expect(keys => keys[</code><code class="c# string">"file"</code><code class="c# plain">]).Returns(postedfile.Object);</code></div>
<div class="line number23 index22 alt2">
</div>
<div class="line number24 index23 alt1">
<code class="c# spaces"> </code><code class="c# comments">//OK, Mock Framework! Give back these values when asked, and I will want to Verify that these things happened</code></div>
<div class="line number25 index24 alt2">
<code class="c# spaces"> </code><code class="c# plain">postedfile.Expect(f => f.ContentLength).Returns(8192).Verifiable();</code></div>
<div class="line number26 index25 alt1">
<code class="c# spaces"> </code><code class="c# plain">postedfile.Expect(f => f.FileName).Returns(</code><code class="c# string">"foo.doc"</code><code class="c# plain">).Verifiable();</code></div>
<div class="line number27 index26 alt2">
</div>
<div class="line number28 index27 alt1">
<code class="c# spaces"> </code><code class="c# comments">//OK, Mock Framework! Someone is going to call SaveAs, but only once!</code></div>
<div class="line number29 index28 alt2">
<code class="c# spaces"> </code><code class="c# plain">postedfile.Expect(f => f.SaveAs(It.IsAny<</code><code class="c# keyword">string</code><code class="c# plain">>())).AtMostOnce().Verifiable();</code></div>
<div class="line number30 index29 alt1">
<code class="c# spaces"> </code> </div>
<div class="line number31 index30 alt2">
<code class="c# spaces"> </code><code class="c# plain">HomeController controller = </code><code class="c# keyword">new</code> <code class="c# plain">HomeController();</code></div>
<div class="line number32 index31 alt1">
<code class="c# spaces"> </code><code class="c# comments">//Set the controller's context to the mock! (fake)</code></div>
<div class="line number33 index32 alt2">
<code class="c# spaces"> </code><code class="c# plain">controller.ControllerContext = </code><code class="c# keyword">new</code> <code class="c# plain">ControllerContext(context.Object, </code><code class="c# keyword">new</code> <code class="c# plain">RouteData(), controller);</code></div>
<div class="line number34 index33 alt1">
</div>
<div class="line number35 index34 alt2">
<code class="c# spaces"> </code><code class="c# comments">//DO IT!</code></div>
<div class="line number36 index35 alt1">
<code class="c# spaces"> </code><code class="c# plain">ViewResult result = controller.UploadFiles() </code><code class="c# keyword">as</code> <code class="c# plain">ViewResult;</code></div>
<div class="line number37 index36 alt2">
</div>
<div class="line number38 index37 alt1">
<code class="c# spaces"> </code><code class="c# comments">//Now, go make sure that the Controller did its job</code></div>
<div class="line number39 index38 alt2">
<code class="c# spaces"> </code><code class="c# plain">var uploadedResult = result.ViewData.Model </code><code class="c# keyword">as</code> <code class="c# plain">List<ViewDataUploadFilesResult>;</code></div>
<div class="line number40 index39 alt1">
<code class="c# spaces"> </code><code class="c# plain">Assert.AreEqual(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, </code><code class="c# string">"foo.doc"</code><code class="c# plain">), uploadedResult[0].Name);</code></div>
<div class="line number41 index40 alt2">
<code class="c# spaces"> </code><code class="c# plain">Assert.AreEqual(8192, uploadedResult[0].Length);</code></div>
<div class="line number42 index41 alt1">
</div>
<div class="line number43 index42 alt2">
<code class="c# spaces"> </code><code class="c# plain">postedfile.Verify();</code></div>
<div class="line number44 index43 alt1">
<code class="c# plain">}</code></div>
</div>
</td></tr>
</tbody></table>
</div>
</div>
<h3>
How to do File Upload with ASP.NET MVC </h3>
Now, what is the least amount of code in our Controller do we need to write to make this test pass? Here we get to use the Request.Files method that ASP.NET (not ASP.NET MVC) has had for years, and use it as advertised. It works in the tests and it works in production. <br />
<blockquote>
<strong>Important Note: </strong>We have to use the HttpPostedFileBase class, rather than the HttpPostedFile because every Request, Response, HttpContext and all related ASP.NET intrinsic abstractions are one layer farther way in ASP.NET MVC. If you get an HttpRequest in ASP.NET, then in ASP.NET MVC at runtime...<br />
<ul>
<li>you'll get an HttpRequestWrapper while running under a Webserver </li>
<li>you'll get a dynamically generated derived Mock of an HttpRequestBase while running outside a Webserver (like inside a test) when you've made your own ControllerContext. </li>
</ul>
In each case, the instances you'll get are both (ultimately) of type HttpRequestBase, but it's this extra layer of abstraction that makes ASP.NET MVC easy to test and ASP.NET WebForms less so. I hope these Wrappers will be included in a future release of WebForms. The fact that they live in the System.Web.Abstractions.dll and not System.Web.Mvc.Abstractions.dll tells me someone has their eye on that particular ball.</blockquote>
At any rate, here's the Controller that takes File Upload requests:<br />
<div>
<div class="syntaxhighlighter c# ie" id="highlighter_363116">
<div class="toolbar">
?</div>
<table border="0" cellpadding="0" cellspacing="0"><tbody>
<tr><td class="gutter"><div class="line number1 index0 alt2">
1</div>
<div class="line number2 index1 alt1">
2</div>
<div class="line number3 index2 alt2">
3</div>
<div class="line number4 index3 alt1">
4</div>
<div class="line number5 index4 alt2">
5</div>
<div class="line number6 index5 alt1">
6</div>
<div class="line number7 index6 alt2">
7</div>
<div class="line number8 index7 alt1">
8</div>
<div class="line number9 index8 alt2">
9</div>
<div class="line number10 index9 alt1">
10</div>
<div class="line number11 index10 alt2">
11</div>
<div class="line number12 index11 alt1">
12</div>
<div class="line number13 index12 alt2">
13</div>
<div class="line number14 index13 alt1">
14</div>
<div class="line number15 index14 alt2">
15</div>
<div class="line number16 index15 alt1">
16</div>
<div class="line number17 index16 alt2">
17</div>
<div class="line number18 index17 alt1">
18</div>
<div class="line number19 index18 alt2">
19</div>
<div class="line number20 index19 alt1">
20</div>
<div class="line number21 index20 alt2">
21</div>
<div class="line number22 index21 alt1">
22</div>
<div class="line number23 index22 alt2">
23</div>
<div class="line number24 index23 alt1">
24</div>
<div class="line number25 index24 alt2">
25</div>
<div class="line number26 index25 alt1">
26</div>
<div class="line number27 index26 alt2">
27</div>
<div class="line number28 index27 alt1">
28</div>
<div class="line number29 index28 alt2">
29</div>
<div class="line number30 index29 alt1">
30</div>
</td><td class="code"><div class="container">
<div class="line number1 index0 alt2">
<code class="c# keyword">public</code> <code class="c# keyword">class</code> <code class="c# plain">ViewDataUploadFilesResult</code></div>
<div class="line number2 index1 alt1">
<code class="c# plain">{</code></div>
<div class="line number3 index2 alt2">
<code class="c# spaces"> </code><code class="c# keyword">public</code> <code class="c# keyword">string</code> <code class="c# plain">Name { </code><code class="c# keyword">get</code><code class="c# plain">; </code><code class="c# keyword">set</code><code class="c# plain">; }</code></div>
<div class="line number4 index3 alt1">
<code class="c# spaces"> </code><code class="c# keyword">public</code> <code class="c# keyword">int</code> <code class="c# plain">Length { </code><code class="c# keyword">get</code><code class="c# plain">; </code><code class="c# keyword">set</code><code class="c# plain">; }</code></div>
<div class="line number5 index4 alt2">
<code class="c# plain">}</code></div>
<div class="line number6 index5 alt1">
</div>
<div class="line number7 index6 alt2">
<code class="c# keyword">public</code> <code class="c# keyword">class</code> <code class="c# plain">HomeController : Controller</code></div>
<div class="line number8 index7 alt1">
<code class="c# plain">{</code></div>
<div class="line number9 index8 alt2">
<code class="c# spaces"> </code><code class="c# keyword">public</code> <code class="c# plain">ActionResult UploadFiles()</code></div>
<div class="line number10 index9 alt1">
<code class="c# spaces"> </code><code class="c# plain">{</code></div>
<div class="line number11 index10 alt2">
<code class="c# spaces"> </code><code class="c# plain">var r = </code><code class="c# keyword">new</code> <code class="c# plain">List<ViewDataUploadFilesResult>();</code></div>
<div class="line number12 index11 alt1">
</div>
<div class="line number13 index12 alt2">
<code class="c# spaces"> </code><code class="c# keyword">foreach</code> <code class="c# plain">(</code><code class="c# keyword">string</code> <code class="c# plain">file </code><code class="c# keyword">in</code> <code class="c# plain">Request.Files)</code></div>
<div class="line number14 index13 alt1">
<code class="c# spaces"> </code><code class="c# plain">{</code></div>
<div class="line number15 index14 alt2">
<code class="c# spaces"> </code><code class="c# plain">HttpPostedFileBase hpf = Request.Files[file] </code><code class="c# keyword">as</code> <code class="c# plain">HttpPostedFileBase;</code></div>
<div class="line number16 index15 alt1">
<code class="c# spaces"> </code><code class="c# keyword">if</code> <code class="c# plain">(hpf.ContentLength == 0)</code></div>
<div class="line number17 index16 alt2">
<code class="c# spaces"> </code><code class="c# keyword">continue</code><code class="c# plain">;</code></div>
<div class="line number18 index17 alt1">
<code class="c# spaces"> </code><code class="c# keyword">string</code> <code class="c# plain">savedFileName = Path.Combine(</code></div>
<div class="line number19 index18 alt2">
<code class="c# spaces"> </code><code class="c# plain">AppDomain.CurrentDomain.BaseDirectory, </code></div>
<div class="line number20 index19 alt1">
<code class="c# spaces"> </code><code class="c# plain">Path.GetFileName(hpf.FileName));</code></div>
<div class="line number21 index20 alt2">
<code class="c# spaces"> </code><code class="c# plain">hpf.SaveAs(savedFileName);</code></div>
<div class="line number22 index21 alt1">
</div>
<div class="line number23 index22 alt2">
<code class="c# spaces"> </code><code class="c# plain">r.Add(</code><code class="c# keyword">new</code> <code class="c# plain">ViewDataUploadFilesResult() </code></div>
<div class="line number24 index23 alt1">
<code class="c# spaces"> </code><code class="c# plain">{ Name = savedFileName, </code></div>
<div class="line number25 index24 alt2">
<code class="c# spaces"> </code><code class="c# plain">Length = hpf.ContentLength });</code></div>
<div class="line number26 index25 alt1">
<code class="c# spaces"> </code><code class="c# plain">}</code></div>
<div class="line number27 index26 alt2">
<code class="c# spaces"> </code><code class="c# keyword">return</code> <code class="c# plain">View(</code><code class="c# string">"UploadedFiles"</code><code class="c# plain">,r);</code></div>
<div class="line number28 index27 alt1">
<code class="c# spaces"> </code><code class="c# plain">}</code></div>
<div class="line number29 index28 alt2">
<code class="c# plain">}</code></div>
</div>
</td></tr>
</tbody></table>
</div>
</div>
At the bottom where I ask for the "UploadedFiles" view, and I pass in my list of ViewDataUploadFilesResults. This will appea in the ViewData.Model property. The View then displays them, and that's ALL the View does.<br />
<br />
<div>
<div class="syntaxhighlighter c# ie" id="highlighter_309529">
<div class="toolbar">
?</div>
<table border="0" cellpadding="0" cellspacing="0"><tbody>
<tr><td class="gutter"><div class="line number1 index0 alt2">
1</div>
<div class="line number2 index1 alt1">
2</div>
<div class="line number3 index2 alt2">
3</div>
<div class="line number4 index3 alt1">
4</div>
<div class="line number5 index4 alt2">
5</div>
</td><td class="code"><div class="container">
<div class="line number1 index0 alt2">
<code class="c# plain"><ul></code></div>
<div class="line number2 index1 alt1">
<code class="c# plain"><% </code><code class="c# keyword">foreach</code> <code class="c# plain">(ViewDataUploadFilesResult v </code><code class="c# keyword">in</code> <code class="c# keyword">this</code><code class="c# plain">.ViewData.Model) { %></code></div>
<div class="line number3 index2 alt2">
<code class="c# spaces"> </code><code class="c# plain"><%=String.Format(</code><code class="c# string">"<li>Uploaded: {0} totalling {1} bytes.</li>"</code><code class="c# plain">,v.Name,v.Length) %></code></div>
<div class="line number4 index3 alt1">
<code class="c# plain"><% } %> </code></div>
<div class="line number5 index4 alt2">
<code class="c# plain"></ul></code></div>
</div>
</td></tr>
</tbody></table>
</div>
</div>
<h3>
Conclusion</h3>
I always encourage people to take the little bit of time to use Fiddler or SysInternals or look at your call stack or just to take a breath and remind oneself, "so how is this supposed to work?" Otherwise, one is just cargo-cult programming.<br />
<br />
This post was a long answer to the question "How do I do FileUpload with ASP.NET MVC?" but I feel better having written in this way.</div>
</div>
Erichttp://www.blogger.com/profile/02676710416649644137noreply@blogger.com0tag:blogger.com,1999:blog-5617284324004521565.post-80010599568449322252012-02-04T11:14:00.000-08:002012-02-04T11:14:33.896-08:00A Brief Explanation of HttpModule and HttpHandler<h3 class="post-title entry-title"><span style="color: #1a5291;">A Brief Explanation of HttpModule and HttpHandler</span></h3><h3 style="text-align: justify;"><span class="Apple-style-span" style="font-family: "Trebuchet MS", sans-serif;">An HTTP request from client to server can be explained as a chain of IIS, AspNET_ISAPI, Asp.NET Work Processor, HttpModules and HttpHandlers. The last part of the chain which is HttpHandler, creates the HTML and sends the result to HttpModule. AspNet_IASPI.dll is used for Asp.NET pages. And chain completes in reverse order this time, as shown below:</span></h3><h3 class="post-title entry-title"><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg_b1lN4oFPHUfgoGaKQWTElk7_lsb0a-6uSoufZCHuLCuz_dCiRw0cg1VYGFqoVldGiFHemPd2REMtgn98sJDKdYULdnG2MHe5W7XsWiszPSLsuoixqoT9vnwUdC1-btloTCWknodyc8gL/s1600/httphandlersandmodules.PNG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" closure_uid_5jkty1="2" height="287" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg_b1lN4oFPHUfgoGaKQWTElk7_lsb0a-6uSoufZCHuLCuz_dCiRw0cg1VYGFqoVldGiFHemPd2REMtgn98sJDKdYULdnG2MHe5W7XsWiszPSLsuoixqoT9vnwUdC1-btloTCWknodyc8gL/s400/httphandlersandmodules.PNG" width="400" /></a></td></tr>
</tbody></table></h3><h3 class="post-title entry-title"><br />
<span class="Apple-style-span" style="font-family: "Trebuchet MS", sans-serif;">HttpModules and Usage:</span><br />
</h3><h3 style="text-align: justify;"><span class="Apple-style-span" style="font-family: "Trebuchet MS", sans-serif;">We can use several predefined methods of the Global.asax file to perform actions on start/end of the application, on start/end of the request etc., and an HttpModule do the same thing with more modularity. So, an HttpModule can be thought as a modular alternative of Global.asax file and its usage is recommended.</span></h3><h3 style="text-align: justify;"><span class="Apple-style-span" style="font-family: "Trebuchet MS", sans-serif;"><br />
</span> </h3><h3 style="text-align: justify;"><span class="Apple-style-span" style="font-family: "Trebuchet MS", sans-serif;">For creating an HttpModule, you should implement IHttpModule interface, and then Init and Dispose methods. We can use HttpApplication object:</span></h3><code></code><h3 class="post-title entry-title"><br />
<code><span class="Apple-style-span" style="font-family: Georgia, "Times New Roman", serif;"><b><span class="Apple-style-span" style="color: #0b5394;">using </span></b>System;</span></code><br />
<code><span class="Apple-style-span" style="font-family: Georgia, "Times New Roman", serif;"><b><span class="Apple-style-span" style="color: #0b5394;">using </span></b>System.Web;</span></code><br />
<code><span class="Apple-style-span" style="font-family: Georgia, "Times New Roman", serif;"><b><span class="Apple-style-span" style="color: #0b5394;">namespace </span></b>CodeBalance.Web</span></code><br />
<code><span class="Apple-style-span" style="font-family: Georgia, "Times New Roman", serif;">{</span></code><br />
<code><span class="Apple-style-span" style="font-family: Georgia, "Times New Roman", serif;"> <b><span class="Apple-style-span" style="color: #0b5394;">public class </span></b>ExampleHttpModule : IHttpModule</span></code><br />
<code><span class="Apple-style-span" style="font-family: Georgia, "Times New Roman", serif;"> {</span></code><br />
<code><span class="Apple-style-span" style="font-family: Georgia, "Times New Roman", serif;"> <b><span class="Apple-style-span" style="color: #0b5394;">public void </span></b>Init(HttpApplication app)</span></code><br />
<code><span class="Apple-style-span" style="font-family: Georgia, "Times New Roman", serif;"> {</span></code><br />
<code><span class="Apple-style-span" style="font-family: Georgia, "Times New Roman", serif;"> app.BeginRequest += new EventHandler(newBeginRequest);</span></code><br />
<code><span class="Apple-style-span" style="font-family: Georgia, "Times New Roman", serif;"> }</span></code><br />
<code><span class="Apple-style-span" style="font-family: Georgia, "Times New Roman", serif;"> <b><span class="Apple-style-span" style="color: #0b5394;">public void </span></b>Dispose()</span></code><br />
<code><span class="Apple-style-span" style="font-family: Georgia, "Times New Roman", serif;"> {</span></code><br />
<code><span class="Apple-style-span" style="font-family: Georgia, "Times New Roman", serif;"> // dispose operations, if necessary</span></code><br />
<code><span class="Apple-style-span" style="font-family: Georgia, "Times New Roman", serif;"> }</span></code><br />
<code><span class="Apple-style-span" style="font-family: Georgia, "Times New Roman", serif;"> <b><span class="Apple-style-span" style="color: #0b5394;">void new</span></b>BeginRequest(<b><span class="Apple-style-span" style="color: #0b5394;">object </span></b>sender, EventArgs e)</span></code><br />
<code><span class="Apple-style-span" style="font-family: Georgia, "Times New Roman", serif;"> {</span></code><br />
<code><span class="Apple-style-span" style="font-family: Georgia, "Times New Roman", serif;"> HttpApplication context = (HttpApplication)sender;</span></code><br />
<code><span class="Apple-style-span" style="font-family: Georgia, "Times New Roman", serif;"> string Url = context.Context.Request.RawUrl;</span></code><br />
<code><span class="Apple-style-span" style="font-family: Georgia, "Times New Roman", serif;"> <b><span class="Apple-style-span" style="color: #0b5394;">if </span></b>(!Url.Contains("SystemMonitoring.aspx"))</span></code><br />
<code><span class="Apple-style-span" style="font-family: Georgia, "Times New Roman", serif;"> {</span></code><br />
<code><span class="Apple-style-span" style="font-family: Georgia, "Times New Roman", serif;"> // show error page</span></code><br />
<code><span class="Apple-style-span" style="font-family: Georgia, "Times New Roman", serif;"> }</span></code><br />
<code><span class="Apple-style-span" style="font-family: Georgia, "Times New Roman", serif;"> }</span></code><br />
<code><span class="Apple-style-span" style="font-family: Georgia, "Times New Roman", serif;"> }</span></code><br />
<code><span class="Apple-style-span" style="font-family: Georgia, "Times New Roman", serif;">}</span></code><br />
<code><span class="Apple-style-span" style="font-family: Georgia, "Times New Roman", serif;"></span></code><span class="Apple-style-span" style="font-family: Georgia, "Times New Roman", serif;"></span><br />
<span class="Apple-style-span" style="font-family: "Trebuchet MS", sans-serif;">You can easily add/remove HttpModule via web.config file:</span></h3><h3 class="separator" style="clear: both; text-align: center;"> </h3><h3 class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh76AeUWx0vjJ6WMUM5wBkUYH9fRNFRpda_yvsU8JzlGx1pC5qimGecIRjni-ok-wdsM1mPL_0I9v4DB3jDpkENP_UtGG9gBl2YzwCFRaDN-TzJVhq5fPJJfcD5Ug6URoBEO506pEWPNVyh/s1600/httpModuleConfig.PNG" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" closure_uid_5jkty1="3" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh76AeUWx0vjJ6WMUM5wBkUYH9fRNFRpda_yvsU8JzlGx1pC5qimGecIRjni-ok-wdsM1mPL_0I9v4DB3jDpkENP_UtGG9gBl2YzwCFRaDN-TzJVhq5fPJJfcD5Ug6URoBEO506pEWPNVyh/s1600/httpModuleConfig.PNG" /></a></h3><h3 class="post-title entry-title"><br />
<br />
<b><span class="Apple-style-span" style="font-family: "Trebuchet MS", sans-serif;">HttpHandlers and Usage:</span></b><br />
</h3><h3 style="text-align: justify;"><span class="Apple-style-span" style="font-family: "Trebuchet MS", sans-serif;">HttpHandlers define actions for different type of requested files. They also can perform actions even if that file does not exist. An HTML page can perform all of the operations of an HttpHandler. But an HttpHandler has better performance and has more modularity than pages.</span></h3><h3 style="text-align: justify;"><span class="Apple-style-span" style="font-family: "Trebuchet MS", sans-serif;"><br />
</span> </h3><h3 style="text-align: justify;"><span class="Apple-style-span" style="font-family: "Trebuchet MS", sans-serif;">For creating an HttpHandler, you should implement IHttpHandler interface and then IsReusable and ProcessRequest methods. We can use HttpContext's Request and Response objects</span>:</h3><code></code><h3 class="post-title entry-title"><br />
<code><span class="Apple-style-span" style="font-family: Georgia, "Times New Roman", serif;"><b><span class="Apple-style-span" style="color: #0b5394;">using </span></b>System;</span></code><br />
<code><span class="Apple-style-span" style="font-family: Georgia, "Times New Roman", serif;"><b><span class="Apple-style-span" style="color: #0b5394;">using </span></b>System.Web;</span></code><br />
<code><span class="Apple-style-span" style="font-family: Georgia, "Times New Roman", serif;"><b><span class="Apple-style-span" style="color: #0b5394;">namespace </span></b>CodeBalance.Web</span></code><br />
<code><span class="Apple-style-span" style="font-family: Georgia, "Times New Roman", serif;">{</span></code><br />
<code><span class="Apple-style-span" style="font-family: Georgia, "Times New Roman", serif;"> <b><span class="Apple-style-span" style="color: #0b5394;">public class </span></b>ExampleHttpHandler : IHttpHandler</span></code><br />
<code><span class="Apple-style-span" style="font-family: Georgia, "Times New Roman", serif;"> {</span></code><br />
<code><span class="Apple-style-span" style="font-family: Georgia, "Times New Roman", serif;"> <b><span class="Apple-style-span" style="color: #0b5394;">public void </span></b>IsReusable(HttpApplication app)</span></code><br />
<code><span class="Apple-style-span" style="font-family: Georgia, "Times New Roman", serif;"> {</span></code><br />
<code><span class="Apple-style-span" style="font-family: Georgia, "Times New Roman", serif;"> // readonly.determines if this handler can be used in another requests</span></code><br />
<code><span class="Apple-style-span" style="font-family: Georgia, "Times New Roman", serif;"> }</span></code><br />
<code><span class="Apple-style-span" style="font-family: Georgia, "Times New Roman", serif;"> <b><span class="Apple-style-span" style="color: #0b5394;">public void </span></b>ProcessRequest(HttpContext context)</span></code><br />
<code><span class="Apple-style-span" style="font-family: Georgia, "Times New Roman", serif;"> {</span></code><br />
<code><span class="Apple-style-span" style="font-family: Georgia, "Times New Roman", serif;"> context.Response.Write("Hello World!");</span></code><br />
<code><span class="Apple-style-span" style="font-family: Georgia, "Times New Roman", serif;"> }</span></code><br />
<code><span class="Apple-style-span" style="font-family: Georgia, "Times New Roman", serif;"> }</span></code><br />
<code><span class="Apple-style-span" style="font-family: Georgia, "Times New Roman", serif;">}</span></code><br />
<code><span class="Apple-style-span" style="font-family: Georgia, "Times New Roman", serif;"></span></code><span class="Apple-style-span" style="font-family: Georgia, "Times New Roman", serif;"></span><br />
<span class="Apple-style-span" style="font-family: "Trebuchet MS", sans-serif;">You can easily add/remove HttpHandler via web.config file:</span></h3><h3 class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEisTep_71Ms8dSTrOw01Tuco9QzcexcGZ8yLvGx8OoqKP9e77DnqJmoWr4t1-LMeWw__cn51VLWOxez-QPCPRsAhkyof9ZNhpDQD83k0kvDO1Io2Cd7WR6bWF1Siu0EqfDhzoeJv9ut57CA/s1600/httHandlerConfig.PNG" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" closure_uid_5jkty1="4" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEisTep_71Ms8dSTrOw01Tuco9QzcexcGZ8yLvGx8OoqKP9e77DnqJmoWr4t1-LMeWw__cn51VLWOxez-QPCPRsAhkyof9ZNhpDQD83k0kvDO1Io2Cd7WR6bWF1Siu0EqfDhzoeJv9ut57CA/s1600/httHandlerConfig.PNG" /></a></h3><div class="separator" style="clear: both; text-align: left;">Another way to differentiate between a HttpModule and an HttpHandler is this:</div><div class="separator" style="clear: both; text-align: left;"><br />
</div><div class="separator" style="clear: both; text-align: left;">HttpModules are used to redirect url's or to attach a HttpCookie to the http stream.</div><div class="separator" style="clear: both; text-align: left;"><br />
</div><div class="separator" style="clear: both; text-align: left;">HttpHandlers are used to server a custom data type to the http stream. One of many examples would be if you had photos in a database that you wanted to display on a page, you're only option is an HttpHandler.</div><div class="separator" style="clear: both; text-align: left;"><br />
</div><div class="separator" style="clear: both; text-align: center;"><br />
</div><div class="separator" style="clear: both; text-align: center;"><br />
</div><div align="left" class="separator" style="clear: both; text-align: center;"></div><h3 class="post-title entry-title"> </h3>Erichttp://www.blogger.com/profile/02676710416649644137noreply@blogger.com0tag:blogger.com,1999:blog-5617284324004521565.post-76260712890022788202012-02-02T04:23:00.000-08:002012-02-02T04:23:39.710-08:0015 Best Practices for Exception Handling1) Don't manage business logic with exceptions. Use conditional statements instead. If a control can be done with if-else statement clearly, don't use exceptions because it reduces readability and performance (e.g. null control, divide by zero control).<br />
<br />
2) Exception names must be clear and meaningful, stating the causes of exception. <br />
<br />
3) Throw exceptions for error conditions while implementing a method. E.g. if you return -1, -2, -3 etc. values instead of FileNotFoundException, that method can not be understand. <br />
<br />
4) Catch specific exceptions instead of the top Exception class. This will bring additional performance, readability and more specific exception handling. <br />
<br />
5) Null control with conditionals is not an alternative to catching NullPointerException. If a method may return null, control it with if-else statement. If a return may throw NullPointerException, catch it. <br />
<br />
6) Try not to re-throw the exception because of the price. Bu if re-throwing had been a must, re-throw the same exception instead of creating a new exception. This will bring additional performance. You may add additional info in each layer to that exception. <br />
<br />
7) Define your own exception hierarchy by extending current Exception class (e.g. UserException, SystemException and their sub types) and use them. By doing this you can specialize your exceptions and define a reusable module/layer of exceptions. <br />
<br />
8) Use types of exceptions clearly. Fatal: System crash states. Error: Lack of requirement. Warn: Not an error but error probability. Info: Info for user. Debug: Info for developer. <br />
<br />
9) Don't absorb exceptions with no logging and operation. Ignoring exceptions will save that moment but will create a chaos for maintainability later. <br />
<br />
10) Don't log the same exception more than once. This will provide clearness of the exception location. <br />
<br />
11) Always clean up resources (opened files etc.) and perform this in "finally" blocks. <br />
<br />
12) Exception handling inside a loop is not recommended for most cases. Surround the loop with exception block instead. <br />
<br />
13) Granularity is very important. One try block must exist for one basic operation. So don't put hundreds of lines in a try-catch statement. <br />
<br />
14) Produce enough documentation for your exceptions (at least JavaDoc). <br />
<br />
15) Giving a number/code for each different exception message is a good practice for documentation and faster communication.Erichttp://www.blogger.com/profile/02676710416649644137noreply@blogger.com0tag:blogger.com,1999:blog-5617284324004521565.post-24674529437364262162011-09-12T17:04:00.000-07:002011-09-13T11:44:54.802-07:00Encryption/Decryption is now workingEncryption/Decryption is now working! You can see how it works here: <br />
<text><br />
public static string Encrypt( string target ) <br />
{<br />
byte[] ptextBytes = Encoding.ASCII.GetBytes( target);<br />
byte[] ctextBytes = ProtectedData.Protect( ptextBytes, entropy,<br />
SCOPE );<br />
char[] chars = new char[1024];<br />
Convert.ToBase64CharArray( ctextBytes, 0, <br />
ctextBytes.GetLength(0), chars, 0 );<br />
return ToString( chars );<br />
}<br />
<br />
public static string Decrypt( string target )<br />
{<br />
byte[] ctextBytes = Convert.FromBase64String( target );<br />
byte[] ptextBytes = ProtectedData.Unprotect( ctextBytes, entropy,<br />
SCOPE );<br />
return Encoding.ASCII.GetString( ptextBytes );<br />
}<br />
<br />
private static string ToString( char[] chars )<br />
{<br />
StringBuilder sb = new StringBuilder();<br />
foreach ( char c in chars )<br />
if( c != (char) 0 )<br />
sb.Append( c );<br />
<br />
return sb.ToString();<br />
}<br />
</text><br />
<p>entropy is defined as: <br />
</p><p>private static byte[] entropy = new byte[] { 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 }; // not the real values used for obvious reasons!<br />
</p><p>SCOPE is defined as: <br />
</p><p>private const DataProtectionScope SCOPE = DataProtectionScope.LocalMachine; // this will be using the web servers encryption key.<br />
</p><p>The 'trick' to getting this code working was to only copy the non-zero characters from the chars array.</p>Erichttp://www.blogger.com/profile/02676710416649644137noreply@blogger.com0tag:blogger.com,1999:blog-5617284324004521565.post-41661945364285623302011-09-10T12:49:00.000-07:002011-09-10T12:49:11.342-07:00Working on Encryption/Decryption for the siteI already have a better hash working for passwords on the site that use a unique salt value and repeat the hash 10,000 times:<br />
<br />
public static byte[] Encode( string password, out byte[] salt )<br />
{<br />
Rfc2898DeriveBytes rdb = new Rfc2898DeriveBytes( password, <br />
32, 10000 );<br />
salt = rdb.Salt;<br />
return rdb.GetBytes( 256 );<br />
}<br />
<br />
public static bool ValidatePassword( string password, <br />
byte[] storedSalt, <br />
byte[] encPassword )<br />
{<br />
Rfc2898DeriveBytes rdb = new Rfc2898DeriveBytes( password,<br />
storedSalt, <br />
10000 );<br />
byte[] passwordEnc = rdb.GetBytes( 256 );<br />
return Equals( encPassword, passwordEnc );<br />
}<br />
<br />
At the moment, I'm having some difficulty getting a Base64 string in the correct format, but once I get that issue solved (over the next two or three days), I'll post those two methods here just like I did for the two that are working as designed.Erichttp://www.blogger.com/profile/02676710416649644137noreply@blogger.com0tag:blogger.com,1999:blog-5617284324004521565.post-41051211657302422472011-08-27T16:45:00.000-07:002011-08-27T17:10:01.325-07:00Okay, the Password generator is done.<br />
<br />
This is how it works:<br />
<br />
Step 1) You enter a master password (with this password you will always get the same 26x26 matrix.<br />
Step 2) Follow the directions on the Cypher page.<br />
<br />
The master password: mycustompassword will always result in this matrix and<br />
the master password: MYCUSTOMPASSWORD will always result in this matrix too.<br />
<br />
This is because the letters are reduced to their index from 'A', 'a' or ' '.<br />
<br />
x p m w c b f j k g l r z e u n a s i y o q v d h t <br />
e v b d q r l h w y t j o a n i m c s k u p f g z x <br />
q l z g m f c x i j w v t s a d r k h y b p n o e u <br />
l u t b m w p f q v g a c y o d i r n x z e s h j k <br />
y m t j p e o q g b a c h s u x l f z v n k d w r i <br />
w e n f g y u v a m x k j l p i q c o z s d r b t h <br />
h l g i m c e o f w k a j d z v p s b q t y n u x r <br />
f h j r i t p x l u c d z n s o m b a e y w v q k g <br />
m l q e b v h y o f w s j k c z u t a g p n r i x d <br />
z i o v q p h r n x y c b a w d f j k t g u s e m l <br />
l v i r c m u n x k b y q j p e a d z h t g f s o w <br />
v m s d q y n a p b f j g h u w k e z i l c o t x r <br />
d v f r m n t b g o c y l e j q i k x h u w z s p a <br />
e p d y l f o s g u n q t a z k h v b j m r x c w i <br />
r x m c l t e f k n i q j y a w p z s o v u b d h g <br />
t o g z l q h d b w n v m p y e a x k j f c u i r s <br />
u t h r x b q e y a j l z c s m n d v g w k p i o f <br />
m t v f w u r g h b j l q d p y c o a s x k n i z e <br />
y u z v b d f r k o t c l i a w p m q e x s n j g h <br />
t u o f w p m s v b q i n r a l y d k h z c e x j g <br />
y m o s f r h b u x d n c i e g t j z a q l w p v k <br />
j s u o h w v d l b p f r t e n k y x z g m a c i q <br />
v n l e x h p r o j y m s b z g w t k f q d c u a i <br />
d k h y f e l u c m x t z j q i r p g a v s o b n w <br />
u p t h m a d o q b w r j c n z y v s e i k x g f l <br />
z l j r q d t v c u k h f o x b n e s p m a i g w y<br />
<br />
The first step in using this: is to find the first letter in your domain name (like: my-msi.net) scanning from left to right (just omit the non-letters).<br />
<br />
Keep doing this from the spot you left off on for each successive letter of the domain name.<br />
<br />
Rember the spot you ended up at: This is your starting place for the encryption process.<br />
<br />
Now the encryption can begin:<br />
<br />
To encrypt we will once again find the first letter in the domain name (like: my-msi.net), but this time we will right down the next two letters.<br />
<br />
Then we will find the next letter in the domain name, but this time we will write down the next two letters above that point.<br />
<br />
Then we will find the next letter in the domain name, but this time we will write down the next two letters to the left of that point.<br />
<br />
Then we will find the next letter in the domain name, but this time we well write down the next two letters below that point.<br />
<br />
Repeat, rotating the direction you take the next two letters from going counter-clockwise.<br />
<br />
And that's it. Print this page and you'll have an off-line encryption method that is unique to you. Because nobody will have the same 26x26 matrix without your Master Password.<br />
Erichttp://www.blogger.com/profile/02676710416649644137noreply@blogger.com0tag:blogger.com,1999:blog-5617284324004521565.post-89179133959781066242011-08-26T10:53:00.000-07:002011-08-26T11:41:27.825-07:00A HttpModule wasn't required after all...A HttpModule wasn't required after all...<br />
<br />
All that was needed was one fuction (method) and a simple if statement:<br />
<br />
<pre style="background: silver; color: black; font-family: Consolas; font-size: 13px;"> <span style="color: blue;">private</span> <span style="color: blue;">bool</span> CheckHeaders( <span style="color: blue;">string</span> forThis )
{
<span style="color: blue;">bool</span> found = <span style="color: blue;">false</span>;
<span style="color: blue;">foreach</span> ( <span style="color: blue;">string</span> s <span style="color: blue;">in</span> Request.Headers )
<span style="color: blue;">if</span> ( s.Contains( forThis ) )
{
found = <span style="color: blue;">true</span>;
<span style="color: blue;">break</span>;
}
<span style="color: blue;">return</span> found;
}
<span style="color: blue;">public</span> <span style="color: #2b91af;">ActionResult</span> Index( <span style="color: blue;">string</span> memberName )
{
<span style="color: blue;">if</span> ( Request.Browser.IsMobileDevice || CheckHeaders( <span style="color: #a31515;">"iPhone"</span> ) )
<span style="color: blue;">return</span> Redirect( <span style="color: blue;">string</span>.Format( <span style="color: #a31515;">"~/Mobile/Index/{1}"</span>, memberName ) );
<div style="background: silver; color: black; font-family: Consolas; font-size: 13px;"> // rest of this mehtod isn't being shown. </div> }
</div></pre><br />
And that's all for now. I did see a new way to generate site passwords with tons of entripy today and I'll be working on a more automated implementation of that next.</div>Erichttp://www.blogger.com/profile/02676710416649644137noreply@blogger.com0tag:blogger.com,1999:blog-5617284324004521565.post-65795693063214428262011-08-25T16:54:00.000-07:002011-08-25T16:54:56.442-07:00The site is almost ready for mobile devicesThe site is almost ready for mobile devices. At least the pages and controller are done for mobile devices. All that needs to be added is an HttpModule class to detect a mobile device and redirect to the mobile version of the site.<br />
<br />
One thing I like about MVC 3 is that this time the site isn't using any cookies at all (unless asked to on the yet to be completed login page),Erichttp://www.blogger.com/profile/02676710416649644137noreply@blogger.com0tag:blogger.com,1999:blog-5617284324004521565.post-89393326115991552522011-08-22T14:31:00.000-07:002011-08-22T14:31:50.695-07:00Over the past two days some things got done...Over the past two days two things got done...<br />
<br />
Finally got that important Remove/Me page working.<br />
<br />
Why do I call that Remove/Me page important? Have you ever read the CanSpam act that was signed into law a few years back? I'm paraphrasing here, but the key to sending legal 'spam' is to have a working removal link in the email. Our members can purchase lists of people interested in looking at business opportunities and using one of our applictions easily send personalized emails to all of them with just one mouse click. Every email sent out out must by law have a working removal link and that link for this site is: <a href="http://www.my-msi.net/Remove/Me/%7BMemberName%7D?Email={email">http://www.my-msi.net/Remove/Me/%7BMemberName%7D?Email={email</a> later this Fall when we get the web server up and running again.<br />
<br />
What was the second thing?<br />
<br />
In our Contact Management System there is a process where key phrases are replaced, mostly with text the user has entered, but for the RemovalLink there is a url that needed to be updated and that got done today.<br />
<br />
We're at a standstill until we get our database issue resolved hopefully sometime later this week.<br />
Erichttp://www.blogger.com/profile/02676710416649644137noreply@blogger.com0tag:blogger.com,1999:blog-5617284324004521565.post-70191326967412668482011-08-17T11:01:00.000-07:002011-08-17T11:01:29.098-07:00We're moving ahead now!Yep, we're moving ahead now. Got the site working. The member details now appear below the image, and if the image is clicked you get to see the full size image that was stored in the database.<br />
<br />
The following pages are finished:<br />
<br />
Index<br />
Products<br />
<br />
Next up: Getting SQL Server 2005 re-installed (in progress as I'm writing this). Should be finished in another hour or so. Then I'll have to find the local database files or figure out were I stored the production database files (think they are in one of my email clients).<br />
<br />
And then finally, starting on the Matrix page.<br />
<br />
Other pages to be completed this week:<br />
Testimonials - somewhere between simple and the most complex.<br />
AboutUs - simple<br />
Join -which is the most complex page to do, but you wouldn't know it by going through the multi-step join process.<br />
<br />
Then it's on to the really huge task of developing the BackOffice pages again.<br />
<br />
Then I can finally start working on the Web Services and once they are done....<br />
<br />
I can finally start working on the current crop of applications, updating them to support the new encrypted login process.<br />
Erichttp://www.blogger.com/profile/02676710416649644137noreply@blogger.com0tag:blogger.com,1999:blog-5617284324004521565.post-6255621767096325912011-08-16T17:36:00.000-07:002011-08-16T17:36:56.378-07:00Half way thereGot the thumbnail image to display today but for some reason the full image wants to download instead of displaying when the thumbnail image is clicked.<br />
<br />
Also got the ContactUs page working and the first (and hardest) step working on the Products page.working.<br />
<br />
Hopefully I'll have the final part of the image display working tomorrow as well as finishing the Products page and at least starting on the Matrix page.Erichttp://www.blogger.com/profile/02676710416649644137noreply@blogger.com0