<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>C.M. Jackson .Net &#187; Tutorial</title>
	<atom:link href="http://www.cmjackson.net/category/tutorial/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.cmjackson.net</link>
	<description>Web Design, Programming, Tutorials</description>
	<lastBuildDate>Tue, 13 Dec 2011 17:38:12 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3</generator>
		<item>
		<title>Cricket.Net: Part 2 &#8211; Design Discussion</title>
		<link>http://www.cmjackson.net/2011/10/13/cricket-net-part-2-design-discussion/</link>
		<comments>http://www.cmjackson.net/2011/10/13/cricket-net-part-2-design-discussion/#comments</comments>
		<pubDate>Thu, 13 Oct 2011 14:03:47 +0000</pubDate>
		<dc:creator>Chris Jackson</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Tutorial]]></category>
		<category><![CDATA[Website Development]]></category>
		<category><![CDATA[ASP.NET MVC]]></category>
		<category><![CDATA[Onion Architecture]]></category>

		<guid isPermaLink="false">http://www.cmjackson.net/?p=479</guid>
		<description><![CDATA[Summary Cricket.Net is a new open source project that I&#8217;ve started on Codeplex. It will be a web application that will be used for tracking software bugs. Cricket.Net will be written in C# using HTML5, ASP.NET MVC 3, Entity Framework 4.1 Code First, StructureMap, and the Onion Architecture. This project will be an example application [...]]]></description>
			<content:encoded><![CDATA[<p><strong>Summary</strong><br />
Cricket.Net is a new open source project that I&#8217;ve started on Codeplex. It will be a web application that will be used for tracking software bugs. Cricket.Net will be written in C# using HTML5, ASP.NET MVC 3, Entity Framework 4.1 Code First, StructureMap, and the Onion Architecture. This project will be an example application to demonstrate how to use these technologies together to build a web application from the ground up.</p>
<p>I&#8217;ll also be going through using Mercurial both on my system and pushing changes to the Codeplex site.</p>
<p>Cricket.Net Series:</p>
<ul>
<li><a href="http://www.cmjackson.net/2011/10/12/cricket-net-part-1-setting-up-the-initial-project/">Part 1: Setting up the initial project</a></li>
<li>Part 2: Design Discussion<br />
<a href="http://www.cmjackson.net/2011/12/13/cricket-net-part-3-unit-testing/">Part 3: Unit Testing</a></li>
</ul>
<p><strong>What will the application do?</strong><br />
I&#8217;m going to take a step back before continuing with the code and look at what this application is suppose to do. I don&#8217;t need to determine everything up front, instead I&#8217;m going to use an Agile approach and lay down some basic requirements for what the system is suppose to do and if those change as the development progresses, that is fine.</p>
<p>Ususally the first thing I do is think about what information the application needs to store. Cricket.Net is a bug tracking program, so it will need to store information on a specific bug and what application the bug occurred in. I&#8217;m also going to want to track dates for when the bug was created and resolved, the version of the application the bug occurred in and maybe a list of one or more assignees who are working on resolving the bug.</p>
<p>Next, I&#8217;m going to open up Visio and separate these ideas into objects on a database model diagram. Since I&#8217;ve already created my solution folder, I&#8217;m going to add a folder within it called !Design. I&#8217;ll place all of my design files here to keep them with the solution when I update the Mercurial repository.</p>
<p>You don&#8217;t necessarily need to create a diagram of the database, you could just write-up the code using Entity Framework: Code First, but it is nice for non-programmers to have something to look at. Also, complex databases with many relationships can be difficult to work with if you don&#8217;t have a diagram to look at.</p>
<p><a href="http://www.cmjackson.net/wp-content/uploads/2011/10/Database-Diagram.jpg"><img class="alignnone size-medium wp-image-481" title="Database Diagram" src="http://www.cmjackson.net/wp-content/uploads/2011/10/Database-Diagram-300x252.jpg" alt="" width="300" height="252" /></a></p>
<p><strong>Onion Architecture and StructureMap</strong><br />
Now I&#8217;d like to talk for a minute about the Onion Architecture.  Structuring an application in this way separates the business logic from the web and infrastructure components in a way that limits their dependencies on each other. Take a look at the following diagram:</p>
<p><a href="http://www.cmjackson.net/wp-content/uploads/2011/10/Onion-Architecture.jpg"><img class="alignnone size-medium wp-image-482" title="Onion Architecture" src="http://www.cmjackson.net/wp-content/uploads/2011/10/Onion-Architecture-300x125.jpg" alt="" width="300" height="125" /></a></p>
<p>The blue boxes represent a project within the solution. The arrows point to their dependencies. Notice how all projects depend on Core. This is where the business logic classes and interfaces are found. Also, notice how the Web project (in this case will be MVC 3) does not depend on Infrastructure (where the database repositories reside). There is an indirect dependency through the DependencyInjection project. This is where StructureMap (or another IoC framework) lives. StructureMap will wire-up the dependencies between the Web and Infrastructure frameworks using the interfaces found in the Core project.</p>
<p>Why go through all this work to setup your project this way? Encapsulation of components that could be replacable in the future makes it easy to upgrade an application to those new componenets. With Onion Architecture you could switch the entire application over to a different database server and only have to modify the database classes found in the Infrastructure project. As long as the interfaces do not change for those classes, the reset of the application will work as it did previously. This can save much time over rewriting the entire application because the db code is embedded everywhere.</p>
<p>The UI component could be changed as well (in this case the Web project) for a console application. The Core and Infrastructure will function the same, but the application would appear totally different.</p>
<p>Projects Summary:</p>
<ul>
<li><strong>UnitTests</strong> &#8211; As the name implies, it contains all unit testing code. The Moq mocking framework will be used here.</li>
<li><strong>Web</strong> &#8211; This is the user interface project. This contains the controllers, views, view models, and wrapper classes around MVC or web specific operations.</li>
<li><strong>Core</strong> &#8211; This contains all interfaces for the application and business logic including: the domain model and service classes.</li>
<li><strong>DependencyInjection</strong> - This contains the classes needed by StructureMap. StructureMap will register all interfaces and concrete classes used in the application.</li>
<li><strong>Infrastructure</strong> &#8211; This contains any IO wrappers or classes using 3rd party projects (including our own common projects).</li>
</ul>
<p><strong>Unit Testing</strong><br />
When starting a project, I try to get in the habbit of coding a Unit Test first, before anything else. This helps me think about how I want to use a method before I worry about how the method works. This tends to lead to an overall better design of the application. I also try to adhere to the SOLID principles, DRY, and YAGNI by only coding what is needed at the time.</p>
<p>Unit Tests should also be very simple. Test for one condition to be met and pass or fail.</p>
<p><strong>Requirements</strong></p>
<ul>
<li>Allow users to manage Applications (including adding different versions for each).</li>
<li>Allow users to manage their issues.</li>
<li>Allow users to be managed by users.</li>
<li>(Managing each of these includes listing, adding, creating, editing, and deleting).</li>
</ul>
<p>Visit the project site at: <a href="http://cricket.codeplex.com">http://cricket.codeplex.com</a>.<br />
Download the source code from this post at: <a href="http://cricket.codeplex.com/SourceControl/changeset/changes/a115ce901573">http://cricket.codeplex.com/SourceControl/changeset/changes/a115ce901573</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.cmjackson.net/2011/10/13/cricket-net-part-2-design-discussion/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Cricket.Net: Part 1 &#8211; Setting up the initial project</title>
		<link>http://www.cmjackson.net/2011/10/12/cricket-net-part-1-setting-up-the-initial-project/</link>
		<comments>http://www.cmjackson.net/2011/10/12/cricket-net-part-1-setting-up-the-initial-project/#comments</comments>
		<pubDate>Wed, 12 Oct 2011 19:50:32 +0000</pubDate>
		<dc:creator>Chris Jackson</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Tutorial]]></category>
		<category><![CDATA[Website Development]]></category>
		<category><![CDATA[ASP.NET MVC]]></category>

		<guid isPermaLink="false">http://www.cmjackson.net/?p=467</guid>
		<description><![CDATA[Summary Cricket.Net is a new open source project that I&#8217;ve started on Codeplex. It will be a web application that will be used for tracking software bugs. Cricket.Net will be written in C# using HTML5, ASP.NET MVC 3, Entity Framework 4.1 Code First, StructureMap, and the Onion Architecture. This project will be an example application to demonstrate [...]]]></description>
			<content:encoded><![CDATA[<p><strong>Summary</strong><br />
Cricket.Net is a new open source project that I&#8217;ve started on Codeplex. It will be a web application that will be used for tracking software bugs. Cricket.Net will be written in C# using HTML5, ASP.NET MVC 3, Entity Framework 4.1 Code First, StructureMap, and the Onion Architecture. This project will be an example application to demonstrate how to use these technologies together to build a web application from the ground up.</p>
<p>I&#8217;ll also be going through using Mercurial both on my system and pushing changes to the Codeplex site.</p>
<p>Cricket.Net Series:</p>
<ul>
<li>Part 1: Setting up the initial project</li>
<li><a href="http://www.cmjackson.net/2011/10/13/cricket-net-part-2-design-discussion/">Part 2: Design Discussion</a></li>
<li><a href="http://www.cmjackson.net/2011/12/13/cricket-net-part-3-unit-testing/">Part 3: Unit Testing</a></li>
</ul>
<p><strong>Prerequisites</strong><br />
To get started, I&#8217;ll be using Visual Studio 2010 SP1Rel and <a href="http://www.microsoft.com/download/en/details.aspx?displaylang=en&amp;id=1491" target="_blank">ASP.NET MVC 3 Tools Update</a>. Later, I&#8217;ll be using <a href="http://www.microsoft.com/download/en/details.aspx?id=26825" target="_blank">Entity Framework 4.1 Update 1</a> so that I can use Code First. You can either download and install Entity Framework, or we&#8217;ll attempt to install this from the Nuget package first.</p>
<p><strong>Creating A New Project</strong><br />
Initially, I&#8217;m going to start with the basic MVC package created by Visual Studio. After this package is created, I&#8217;m going to create the Mercurial repository so that I can send the code to Codeplex.</p>
<ol>
<li>Open Visual Studio 2010.</li>
<li>Click the File menu, then New, Project.</li>
<li>In the New Project window, under Installed Templates, expand Visual C# and choose Web. Select the template called &#8220;ASP.NET MVC 3 Web Application.&#8221; The Name field will be the default name and namespace of your initial project, the Location will be the folder on your C:\ drive where to store your solution, and the Solution Name is the name of your solution folder (if you wish it to be different).<br />
<a href="http://www.cmjackson.net/wp-content/uploads/2011/10/part1_01.png"><img class="alignnone size-medium wp-image-468" title="New Part window" src="http://www.cmjackson.net/wp-content/uploads/2011/10/part1_01-300x207.png" alt="" width="300" height="207" /></a></li>
<li>After clicking OK, the New ASP.NET MVC 3 Project window pops up. I&#8217;m going to choose Internet Application so that the tooling will allow me to go ahead and create a Unit Test project also. I&#8217;m going to change the name of the Unit Test project to Cricket.UnitTests.<br />
<a href="http://www.cmjackson.net/wp-content/uploads/2011/10/part1_02.png"><img class="alignnone size-medium wp-image-469" title="New ASP.NET MVC 3 Project" src="http://www.cmjackson.net/wp-content/uploads/2011/10/part1_02-300x270.png" alt="" width="300" height="270" /></a></li>
<li>After Visual Studio finishes creating the project, it should look like the image below. The Internet Application template that we had chosen in the previous step has added some files that will may or may not use, but for now we&#8217;ll leave these in the solution and move on to creating the Mercurial repository.<br />
<a href="http://www.cmjackson.net/wp-content/uploads/2011/10/part1_03.png"><img class="alignnone size-medium wp-image-470" title="Initial Solution Explorer" src="http://www.cmjackson.net/wp-content/uploads/2011/10/part1_03-285x300.png" alt="" width="285" height="300" /></a></li>
</ol>
<p><strong>Setting up the Mercurial Repository</strong><br />
If you are unfamiliar with Mercurial, it is a source control application that is very fast and pretty easy to use. Before you can continue with this tutorial, you will need to install at least <a href="http://tortoisehg.bitbucket.org/" target="_blank">TortoiseHg</a> to manage the Mercurial repository from Windows Explorer.  If you&#8217;d also like to work with it from within Visual Studio, you will need <a href="http://visualhg.codeplex.com/" target="_blank">VisualHg</a>.  If you&#8217;d like to know more about what Mercurial can do, check out this <a href="http://tekpub.com/codeplex" target="_blank">video from tekpub.com</a>.</p>
<ol>
<li>If you still have your new solution open in Visual Studio, go to the File menu and choose Close Solution.</li>
<li>Next, browse to the folder where your solution folder is located. (In my case, I need to go to the C:\Users\cjackson\Documents\All Projects\ folder)</li>
<li>Right-click on the Cricket.Net folder and expand the TortoiseHg context menu and choose Create Repository Here.</li>
<li>TortoiseHg will display an Init window. Click the Create button to create the repository.</li>
<li>After the repository has been created, a green check mark icon will appear over the Cricket.Net folder icon.</li>
<li>Open the Cricket.Net folder and then edit the .hgignore file. This file will tell the repository to ignore certain files/folders that are used by Visual Studio and do not need to be version controlled. Paste the text below into the file and save it.</li>
</ol>
<pre class="brush: vb;"># use glob syntax
syntax: glob

*.obj
*.pdb
*.user
*.aps
*.pch
*.vspscc
*.vssscc
*_i.c
*_p.c
*.ncb
*.suo
*.tlb
*.tlh
*.bak
*.cache
*.ilk
*.log
*.lib
*.sbr
*.scc
[Bb]in
[Dd]ebug*/
obj/
[Rr]elease*/
_ReSharper*/
[Tt]humbs.db
[Tt]est[Rr]esult*
[Bb]uild[Ll]og.*
*.[Pp]ublish.xml
*.resharper
</pre>
<p>Next, I&#8217;ll save the initial project into the Mercurial repository.</p>
<ol>
<li><span style="font-family: Consolas;">Return to the folder where your solution is stored. (C:\Users\cjackson\Documents\All Projects\ folder)</span></li>
<li>Right-click on the Cricket.Net folder and choose Hg Commit&#8230;</li>
<li>The Cricket.Net commit window will pop up. On the left pane, click the check box at the top to select all files then in the top-right pane, type in a comment for the commit. After you enter whatever comments you wish, click the Commit button to save the current state of the solution.<br />
<a href="http://www.cmjackson.net/wp-content/uploads/2011/10/part1_05.png"><img class="alignnone size-medium wp-image-475" title="Commit" src="http://www.cmjackson.net/wp-content/uploads/2011/10/part1_05-300x190.png" alt="" width="300" height="190" /></a></li>
<li>Next, for new untracked files, a window may pop up asking to add untracked files. Click Add.</li>
</ol>
<p>To save the current repository to Codeplex, follow these instructions:</p>
<ol>
<li>Return to the folder where your solution is stored. (C:\Users\cjackson\Documents\All Projects\ folder)</li>
<li>Right-click on Cricket.Net and expand the TortoiseHG context menu and choose Synchronize.</li>
<li>Under Remote Repository, change the drop down to HTTPS and enter the name of the repository so the URL looks like this (<a href="http://hg01.codeplex.com/cricket">http://hg01.codeplex.com/cricket</a>)</li>
<li>Click on the <a href="http://www.cmjackson.net/wp-content/uploads/2011/10/part1_06.png"><img class="alignnone size-full wp-image-476" title="Push icon" src="http://www.cmjackson.net/wp-content/uploads/2011/10/part1_06.png" alt="" width="30" height="29" /></a> icon to push changes to Codeplex.</li>
<li>Enter your Codeplex username and password when prompted and the files will be uploaded to Codeplex.</li>
</ol>
<p>Visit the project site at: <a href="http://cricket.codeplex.com">http://cricket.codeplex.com</a>.<br />
Download the source code from this post at: <a href="http://cricket.codeplex.com/SourceControl/changeset/changes/1569d75e695b#">http://cricket.codeplex.com/SourceControl/changeset/changes/1569d75e695b#</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.cmjackson.net/2011/10/12/cricket-net-part-1-setting-up-the-initial-project/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>SharePoint 2010: Verify that the Activity Feed Timer Job is enabled</title>
		<link>http://www.cmjackson.net/2011/01/18/sharepoint-2010-verify-that-the-activity-feed-timer-job-is-enabled/</link>
		<comments>http://www.cmjackson.net/2011/01/18/sharepoint-2010-verify-that-the-activity-feed-timer-job-is-enabled/#comments</comments>
		<pubDate>Tue, 18 Jan 2011 16:40:22 +0000</pubDate>
		<dc:creator>Chris Jackson</dc:creator>
				<category><![CDATA[Software]]></category>
		<category><![CDATA[Tutorial]]></category>
		<category><![CDATA[how to]]></category>
		<category><![CDATA[SharePoint]]></category>
		<category><![CDATA[SharePoint 2010]]></category>

		<guid isPermaLink="false">http://www.cmjackson.net/?p=433</guid>
		<description><![CDATA[Here is another warning message that I received after installing SharePoint 2010.  To fix this issue, follow these steps: Go to Central Administration. Click on &#8220;Monitoring.&#8221; Click on &#8220;Review job definitions&#8221; under &#8220;Timer Jobs.&#8221; Scroll down and click on &#8220;User profile service application &#8211; activity feed job.&#8221; Click &#8220;Enable.&#8221; Now, you can go back to [...]]]></description>
			<content:encoded><![CDATA[<p>Here is another warning message that I received after installing SharePoint 2010.  To fix this issue, follow these steps:</p>
<ul>
<li>Go to Central Administration.</li>
<li>Click on &#8220;Monitoring.&#8221;</li>
<li>Click on &#8220;Review job definitions&#8221; under &#8220;Timer Jobs.&#8221;</li>
<li>Scroll down and click on &#8220;User profile service application &#8211; activity feed job.&#8221;</li>
<li>Click &#8220;Enable.&#8221;</li>
</ul>
<p>Now, you can go back to Central Administration and view the warning message.  Click &#8220;Reanalyze Now&#8221; and after some time the message should go away.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.cmjackson.net/2011/01/18/sharepoint-2010-verify-that-the-activity-feed-timer-job-is-enabled/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>SharePoint 2010: The Unattended Service Account Warning</title>
		<link>http://www.cmjackson.net/2011/01/18/sharepoint-2010-the-unattended-service-account-warning/</link>
		<comments>http://www.cmjackson.net/2011/01/18/sharepoint-2010-the-unattended-service-account-warning/#comments</comments>
		<pubDate>Tue, 18 Jan 2011 16:39:42 +0000</pubDate>
		<dc:creator>Chris Jackson</dc:creator>
				<category><![CDATA[Software]]></category>
		<category><![CDATA[Tutorial]]></category>
		<category><![CDATA[how to]]></category>
		<category><![CDATA[SharePoint]]></category>
		<category><![CDATA[SharePoint 2010]]></category>

		<guid isPermaLink="false">http://www.cmjackson.net/?p=431</guid>
		<description><![CDATA[After installing SharePoint 2010, you may notice warnings appear from the Health Analyzer after the system has been running for a while. &#8220;The Unattended Service Account Application ID is not specified or has an invalid value.&#8221; To fix this issue: Open the Central Administration page. Under &#8220;Application Management,&#8221; click on &#8220;Manage service applications.&#8221; Click on [...]]]></description>
			<content:encoded><![CDATA[<p>After installing SharePoint 2010, you may notice warnings appear from the Health Analyzer after the system has been running for a while.</p>
<p><em>&#8220;The Unattended Service Account Application ID is not specified or has an invalid value.&#8221;</em></p>
<p>To fix this issue:</p>
<ul>
<li>Open the Central Administration page.</li>
<li>Under &#8220;Application Management,&#8221; click on &#8220;Manage service applications.&#8221;</li>
<li>Click on &#8220;Secure service application.&#8221;</li>
<li>Next, in the ribbon at the top of the page, click on &#8220;Generate New Key.&#8221;</li>
<li>Enter a pass phrase and click OK.</li>
<li>Now, in the ribbon, click &#8220;New.&#8221;</li>
<li>For the Target Application ID, enter a unique identifier such as: TARGET_APPLICATION_ID</li>
<li>For the Display Name, enter some descriptive name such as: Target Application ID</li>
<li>Enter your email address.</li>
<li>Make sure to change the Target Application Type to GROUP.</li>
<li>Click Next.</li>
<li>Keep the defaults for the next screen and click Next.</li>
<li>Enter in your administrator account into the Target Application Administrators and Members fields.</li>
<li>Click OK.</li>
<li>Next, go to the Central Administration page.</li>
<li>Under &#8220;Application Management,&#8221; click on &#8220;Manage service applications.&#8221;</li>
<li>Scroll down and click on &#8220;Visio Graphics Service.&#8221;</li>
<li>Click on &#8220;Global Settings.&#8221;</li>
<li>Down at the bottom of the page, enter your target ID (TARGET_APPLICATION_ID) into the Application ID field and click OK.</li>
</ul>
<p>Now, you can go back to your Central Administration page and view the warning messages once again.  Open the &#8220;Unattended Service Account&#8221; message and click &#8220;Reanalyze Now.&#8221;  After some time, the message should go away.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.cmjackson.net/2011/01/18/sharepoint-2010-the-unattended-service-account-warning/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Opening PDF files in SharePoint 2010</title>
		<link>http://www.cmjackson.net/2011/01/14/opening-pdf-files-in-sharepoint-2010/</link>
		<comments>http://www.cmjackson.net/2011/01/14/opening-pdf-files-in-sharepoint-2010/#comments</comments>
		<pubDate>Fri, 14 Jan 2011 13:59:42 +0000</pubDate>
		<dc:creator>Chris Jackson</dc:creator>
				<category><![CDATA[Software]]></category>
		<category><![CDATA[Tutorial]]></category>
		<category><![CDATA[how to]]></category>
		<category><![CDATA[SharePoint]]></category>
		<category><![CDATA[SharePoint 2010]]></category>

		<guid isPermaLink="false">http://www.cmjackson.net/?p=423</guid>
		<description><![CDATA[One problem you may be facing if you are new to SharePoint 2010 is how to open PDF files.  There are a couple different problems you may have noticed.  One: the PDF files do not show a file type icon like the Word or Excel files do, and Two: when you click on a PDF [...]]]></description>
			<content:encoded><![CDATA[<p>One problem you may be facing if you are new to SharePoint 2010 is how to open PDF files.  There are a couple different problems you may have noticed.  One: the PDF files do not show a file type icon like the Word or Excel files do, and Two: when you click on a PDF file to open it, you are presented with a dialog box asking you to Save or Cancel.</p>
<p>By default, SharePoint does not recognize PDF files, so we will have to tell it how to recognize the files to display the pretty icon.</p>
<p>The reason the PDF does not open is because of a new header called X-Download-Options that is passed into your browser and if you are using IE 8, a new security feature will block the file from opening.</p>
<p>While we are setting up PDF files, lets go ahead and configure SharePoint&#8217;s search engine so that it can crawl the contents of PDF files as well.</p>
<p><strong>Opening PDFs</strong></p>
<p>First, let&#8217;s tackle the easiest to fix issue.  A SharePoint web application has two modes that it uses to handle browser files: Permissive and Strict.  The default mode is Strict and will cause SharePoint to send the X-Download-Options header.</p>
<p>To turn off the header:</p>
<ul>
<li>Open your SharePoint Central Administration.</li>
<li>Click on &#8220;Manage web applications.&#8221;</li>
<li>Click on &#8220;SharePoint &#8211; 80.&#8221;</li>
<li>In the ribbon at the top of the page, click &#8220;General Settings.&#8221;</li>
<li>Scroll down the pop up window until you find &#8220;Browser file handling&#8221; and change the selected value from &#8220;Strict&#8221; to &#8220;Permissive.&#8221;</li>
<li>Click OK to save changes.</li>
</ul>
<p><strong>Setting Up The Search Engine To Crawl PDFs</strong></p>
<ul>
<li>Download <a href="http://www.adobe.com/support/downloads/detail.jsp?ftpID=4025">Adobe PDF iFilter 9 for 64 bit platforms </a>from Adobe.</li>
<li>Install iFilter on your SharePoint server (or the server that is running the search service).</li>
<li>Accept all defaults.</li>
</ul>
<p><strong>Showing the PDF Icon</strong></p>
<ul>
<li>Visit <a href="http://www.adobe.com/misc/linking.html">Adobe&#8217;s site </a>to download an image of their PDF icon.  Save a copy of the 17 x 17 image size to C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\14\TEMPLATE\IMAGES\ on your SharePoint server.</li>
<li>Edit the C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\14\TEMPLATE\XML\DOCICON.XML file on your SharePoint server.</li>
<li>Scroll down to the &lt;ByExtension&gt; tag and enter the following between the &lt;ByExtension&gt; and &lt;/ByExtension&gt; tags:<br />
&lt;Mapping Key=&#8221;pdf&#8221; Value=&#8221;pdficon_small.gif&#8221; OpenControl=&#8221;" /&gt;<br />
<span style="color: #ff0000;">* If you want to keep the file organized, check the other keys and enter it in alphabetical order.</span></li>
<li>Save the XML file.</li>
<li>Next, open the SharePoint Central Administration site.</li>
<li>Under &#8220;Application Management&#8221;, click &#8220;Manage service applications.&#8221;</li>
<li>Scroll down the list of applications and click on &#8220;Search service application.&#8221;</li>
<li>In the left-hand menu, click &#8220;File types.&#8221;</li>
<li>Click &#8220;New file type.&#8221;</li>
<li>Enter &#8220;pdf&#8221; into the &#8220;File extension&#8221; box and click OK.</li>
<li>Now, you should be able to scroll down and find your PDF icon.</li>
</ul>
<p>Now, we&#8217;ll need to restart IIS by opening the command prompt on your SharePoint server as Administrator.  Type into the command prompt: &#8220;iisreset&#8221; and IIS will be stopped and restarted.</p>
<p><strong>Running A Full Crawl</strong></p>
<ul>
<li>From the Central Administration, under &#8220;Application Management&#8221;, click on &#8220;Manage service applications.&#8221;</li>
<li>Scroll down and click on &#8220;Search service application.&#8221;</li>
<li>From the left-hand menu, click &#8220;Content Sources.&#8221;</li>
<li>Hover your mouse over the &#8220;Local SharePoint sites&#8221; record and click the down arrow for more options.</li>
<li>Select &#8220;Start full crawl&#8221;</li>
</ul>
<p>Now, you should be able to open PDF files, see adobe icons next to them in library web parts, and be able to search the contents using SharePoint&#8217;s search engine.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.cmjackson.net/2011/01/14/opening-pdf-files-in-sharepoint-2010/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Installing SharePoint 2010</title>
		<link>http://www.cmjackson.net/2011/01/13/installing-sharepoint-2010/</link>
		<comments>http://www.cmjackson.net/2011/01/13/installing-sharepoint-2010/#comments</comments>
		<pubDate>Thu, 13 Jan 2011 21:14:33 +0000</pubDate>
		<dc:creator>Chris Jackson</dc:creator>
				<category><![CDATA[Software]]></category>
		<category><![CDATA[Tutorial]]></category>
		<category><![CDATA[how to]]></category>
		<category><![CDATA[SharePoint]]></category>
		<category><![CDATA[SharePoint 2010]]></category>

		<guid isPermaLink="false">http://www.cmjackson.net/?p=412</guid>
		<description><![CDATA[Here is the installation process that I used for setting up SharePoint 2010 using MSSQL 2005 as the backend database. First, you must make sure if you are going to use SQL 2005 instead of 2008, that your SQL server is patched to a compatible level for SharePoint. Updating Microsoft SQL 2005 First thing you need [...]]]></description>
			<content:encoded><![CDATA[<p>Here is the installation process that I used for setting up SharePoint 2010 using MSSQL 2005 as the backend database.</p>
<p>First, you must make sure if you are going to use SQL 2005 instead of 2008, that your SQL server is patched to a compatible level for SharePoint.</p>
<p><strong>Updating Microsoft SQL 2005</strong></p>
<p>First thing you need to do is make sure your SQL server is patched up.  I ended up using the <a href="http://support.microsoft.com/hotfix/KBHotfix.aspx?kbnum=974648&amp;kbln=en-us">SQL 2005 SP3 Update 6</a> found on Microsoft&#8217;s site.  You need to make sure you select the 64 bit version.  To do that, you must click on the <em>&#8220;Show hotfixes for all platforms and languages (14)&#8221; </em>link above the list of files.  This will display all the files available. </p>
<p>Check the one marked<em> &#8220;SQL_Server_2005_SP3_Cumulative_Update_6&#8243;</em> with the x64 platform type.  Enter your email and submit the form to have the download link sent to you.  The link will contain a password protected self-extracting program, so make sure to get the password from the email.</p>
<p>Copy this patch over to your server and install it.  The SQL server will need to be restarted afterwards, so do so at a time when you can down it for a few minutes.</p>
<p>After patching my SQL server, the version now shows 9.0.4266 in the SQL Server Management Studio Express.</p>
<p><strong>Setting Up A Service Account</strong></p>
<p>SharePoint 2010 will ask for a service account that it uses to communicate with the database.  So, you can go ahead and create your service account in Active Directory, I used svc_sharepoint, and configure SQL 2005 for the new user.</p>
<ul>
<li>From the SQL Server Management Studio Express, connect to your database server and open up the Security\Logins folders in the tree.</li>
<li>Right-click on the Logins folder and choose &#8220;New Login&#8221;</li>
<li>For the &#8220;Login Name&#8221;, enter DOMAINNAME\USERNAME</li>
<li>Click &#8220;Server Roles&#8221; on the left-hand side and put a checkmark next to &#8220;dbcreator&#8221; and &#8220;securityadmin&#8221;.</li>
<li>Click OK.</li>
</ul>
<p><strong>Installing SharePoint 2010</strong></p>
<p>Enter the SharePoint disc into your CD/DVD drive on your server.  If it does not start automatically, execute the &#8220;Splash.hta&#8221; file to see the splash page.</p>
<p><em>Software Prerequisites</em></p>
<ul>
<li>Click on &#8220;Install Software Prerequisites&#8221;.</li>
<li>Accept the default values and start the installation of the secondary programs needed to run SharePoint.</li>
<li>Click Finish when everything has been installed.</li>
</ul>
<p><em>Installation</em></p>
<ul>
<li>Click &#8220;Install SharePoint Server.</li>
<li>Enter your product key. Continue.</li>
<li>When asked for Standalone or Server Farm, choose Server Farm if this is a production server.</li>
<li>Next, Mark the circle next to Complete and click Install Now.</li>
<li>Once everything has finished installing, make sure the &#8220;Run the SharePoint Products and Technologies Configuration Wizard now&#8221; box is checked and click Close.</li>
</ul>
<p><strong>Configuring SharePoint</strong></p>
<p>When the configuration wizard starts, you will be asked if services can be started or reset.  Choose yes.</p>
<ul>
<li>Click &#8220;Create a new server farm&#8221; if this is your first server, otherwise choose &#8220;Connect to an existing server farm.&#8221;</li>
<li>On the next screen, you will need to enter in the name of your database server, as well as the username/password for the service account you had created earlier.  I used svc_sharepoint.  If your database has not been patched up to a compatible level, you will be stopped right here.</li>
<li>The next screen will ask you for a passphrase.  This is an important password that you will need if you want to add another server to this server farm.  <span style="color: #ff0000;">So, don&#8217;t lose it.</span></li>
<li>Next, you&#8217;ll be asked to configure the Central Administration web application.  You can specify a port number that the admin portion of SharePoint will use.  I would use something easy to remember, like 9999.  Keep NTLM selected and hit Next.</li>
<li>If everything looks good on the next page, click Finish.</li>
</ul>
<p><strong>Farm Configuration</strong></p>
<p>Now, a web page should open up and continue the server farm configuration from there.  You will be asked if you want to help make sharepoint better.  Make a choice and hit OK.</p>
<ul>
<li>Select &#8220;Walk me through the settings using the wizard&#8221; and hit Next.</li>
<li>On the next screen, select &#8220;use existing managed account&#8221; and make sure your service account is selected.</li>
<li>Scroll down the page and make sure all services are checked with exception of the Lotus Notes Connector.  Click Next.</li>
<li>The web page will process these settings for a little while.  Once finished, you will be asked to enter the title and description for your main SharePoint site.  Also, you can select a template at the bottom.  I would stick with the default &#8220;Team Site&#8221; template.</li>
<li>Once this has finished, you will get a summary page telling you what services have been enabled.  Click Finish.</li>
</ul>
<p><strong>Changing Your Site URL</strong></p>
<p>After everything has been configured, you will be sent to the Central Administration page.  If you look at your URL, it will show the server name and not the domain address that you would, no doubt, like to use.  For this to work, of course, you need to make sure you have added an ALIAS entry in your DNS server that points your domain name to your SharePoint server name.</p>
<ul>
<li>Under the left-hand menu, click on &#8220;Application Management.&#8221;</li>
<li>Under &#8220;Web Applications&#8221;, click on &#8220;Configure alternate access mappings.&#8221;</li>
<li>In the content area, at the top-right side of the page there is a drop down box next to &#8220;Alternate access mapping collection.&#8221;  Click this drop down and select &#8220;Change alternate access mapping collection.&#8221;</li>
<li>Choose one of the sites displayed (SharePoint &#8211; 80 or Central Administration).</li>
<li>Click &#8220;Add Internal URLs&#8221;</li>
<li>Enter the URL of your domain name (ex. http://my.domainname.com:port).  If this is the Central Administration, you will need to add the port as well.  It can be ommitted if it is your port 80 site.</li>
<li>Choose a zone, such as Intranet, if it applies to what your SharePoint server is used for.</li>
<li>Click Save.</li>
<li>Run through the same steps to add the URL for the other site.</li>
</ul>
<p>Now that SharePoint has been installed and configured, you can continue by setting permissions, creating sites and web parts, and building content.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.cmjackson.net/2011/01/13/installing-sharepoint-2010/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Using the Visual Studio 2010 Remote Debugger with ASP.NET MVC</title>
		<link>http://www.cmjackson.net/2010/11/04/using-the-visual-studio-2010-remote-debugger-with-asp-net-mvc/</link>
		<comments>http://www.cmjackson.net/2010/11/04/using-the-visual-studio-2010-remote-debugger-with-asp-net-mvc/#comments</comments>
		<pubDate>Thu, 04 Nov 2010 19:20:53 +0000</pubDate>
		<dc:creator>Chris Jackson</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Tutorial]]></category>
		<category><![CDATA[ASP.NET MVC]]></category>
		<category><![CDATA[Remote Debugger]]></category>
		<category><![CDATA[Visual Studio 2010]]></category>

		<guid isPermaLink="false">http://www.cmjackson.net/?p=405</guid>
		<description><![CDATA[Visual Studio Remote Debugging Monitor To use the remote debugger with ASP.NET MVC applications, you first must run the Visual Studio Remote Debugger Monitor on the server or remote computer. There are two ways you can do this: - Copy the monitor&#8217;s files to the server or remote computer - Create a shared folder on [...]]]></description>
			<content:encoded><![CDATA[<p><strong>Visual Studio Remote Debugging Monitor</strong></p>
<p>To use the remote debugger with ASP.NET MVC applications, you first must run the Visual Studio Remote Debugger Monitor on the server or remote computer.</p>
<p>There are two ways you can do this:</p>
<p>- Copy the monitor&#8217;s files to the server or remote computer<br />
- Create a shared folder on your developer client and run the monitor on the server from the share.</p>
<p>I will go through the shared folder method. Share out this folder:<br />
C:\Program Files\Microsoft Visual Studio 10.0\Common7\IDE\Remote Debugger</p>
<p>If you server is running a 64-bit OS, use the x64 folder.  For the 32-bit OS, use the x86 folder.</p>
<p><strong>Setting up the server</strong></p>
<p>- Log into the server and navigate to the shared folder on your developer PC. <br />
- Go into the correct folder for your server&#8217;s OS (x86 or x64).<br />
- Run the msvsmon.exe file.  If your server&#8217;s OS is Windows 2008, you will need to right-click on the file and run as Administrator.<br />
- Open Tools -&gt; Permissions.  Make sure that your developer client user is listed here.  If not, add the user and click OK.  Click Yes to allow the user to debug.<br />
- Copy the name of the server (listed on the first line of the Visual Studio Remote Debugging Monitor).<br />
- Return to your developer client.</p>
<p><strong>Debugging remotely</strong></p>
<p>- Make sure the latest version of your application is published to the server (so your source code will be the same as the executed code).<br />
- From Visual Studio 2010, click Debug -&gt; Attach to process.<br />
- Change the value of the Qualifier field to the name of the server on the Visual Studio Remote Debugging Monitor and click Refresh.<br />
- Under the Available Processes, select &#8220;w3wp.exe&#8221; and click Attach.  If you do not see this process listed, then open a web browser and run your application.  After your application has loaded, click the Refresh button and you should see the process.</p>
<p>* If you receive any error messages, you may need to:<br />
- Click Build -&gt; Clean Solution<br />
- Click Build -&gt; Rebuild Solution<br />
- Republish your application to the server<br />
- Click Debug -&gt; Attach To Process</p>
]]></content:encoded>
			<wfw:commentRss>http://www.cmjackson.net/2010/11/04/using-the-visual-studio-2010-remote-debugger-with-asp-net-mvc/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Configuring IIS 6 and ASP.NET MVC</title>
		<link>http://www.cmjackson.net/2010/01/28/configuring-iis-6-and-asp-net-mvc/</link>
		<comments>http://www.cmjackson.net/2010/01/28/configuring-iis-6-and-asp-net-mvc/#comments</comments>
		<pubDate>Thu, 28 Jan 2010 14:00:09 +0000</pubDate>
		<dc:creator>Chris Jackson</dc:creator>
				<category><![CDATA[Tutorial]]></category>
		<category><![CDATA[ASP.NET MVC]]></category>
		<category><![CDATA[how to]]></category>
		<category><![CDATA[IIS 6.0]]></category>

		<guid isPermaLink="false">http://www.cmjackson.net/?p=363</guid>
		<description><![CDATA[By default, IIS 6 does not work with ASP.NET MVC and needs to be configured to use wild-card mapping to get MVC&#8217;s routing and clean URLs to work correctly. Unfortunately, IIS 6 does take a performance hit because all requests are processed by ASP.NET. Static files, such as images, CSS, and JavaScript are processed as [...]]]></description>
			<content:encoded><![CDATA[<p>By default, IIS 6 does not work with ASP.NET MVC and needs to be configured to use wild-card mapping to get MVC&#8217;s routing and clean URLs to work correctly. Unfortunately, IIS 6 does take a performance hit because all requests are processed by ASP.NET. Static files, such as images, CSS, and JavaScript are processed as a dynamic page instead of a static one.</p>
<p><strong>Install ASP.NET MVC</strong><br />
Follow the first two steps of the instructions for <a href="http://www.cmjackson.net/2010/01/15/installing-asp-net-mvc/">installing ASP.NET MVC</a>. The third step can be ignored since Visual Studio will not be installed on the server.</p>
<p><strong>Configuring ASP.NET 2.0</strong><br />
First thing to do is open the IIS Manager -&gt;expand your server -&gt;Web Service Extensions folder. Right-click on the white space under the list of Web Service Extensions and select to Add a new Web service extension&#8230;</p>
<p>The New Web Service Extension window will pop open. Enter &#8220;ASP.NET v2.0.50727&#8243; as the Extension Name and click the Add button.  Browse to the C:\Windows\Microsoft.Net\Framework\v2.0.50727 folder and select the aspnet_isapi.dll file. Make sure to check the &#8220;Set extension status is Allowed&#8221; button before clicking OK.</p>
<p>This will allow your programs to run ASP.NET 2.0, 3.0, and 3.5 versions of the .NET framework.</p>
<p><strong>Configuring Your Web Application</strong><br />
The next thing to do is open the properties of the Web Site where your web application is. Select the ASP.NET tab and select 2.0.50717 in the ASP.NET version drop down box.</p>
<p>Next, click on the Home Directory tab. Click on the Configuration button. Under the Wild-card application maps area, click the Insert button. Browse to the C:\Windows\Microsoft.Net\Framework\v2.0.50727 folder and select the aspnet_isapi.dll file. Uncheck the &#8220;Verify that file exists&#8221; before clicking OK. Save your changes and your site should now be able to run ASP.NET MVC and use the routes setup by your application.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.cmjackson.net/2010/01/28/configuring-iis-6-and-asp-net-mvc/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>ASP.NET MVC Using Forms Authentication With LDAP</title>
		<link>http://www.cmjackson.net/2009/10/23/asp-net-mvc-using-forms-authentication-with-ldap/</link>
		<comments>http://www.cmjackson.net/2009/10/23/asp-net-mvc-using-forms-authentication-with-ldap/#comments</comments>
		<pubDate>Fri, 23 Oct 2009 19:49:03 +0000</pubDate>
		<dc:creator>Chris Jackson</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Tutorial]]></category>
		<category><![CDATA[code]]></category>
		<category><![CDATA[Forms Authentication]]></category>
		<category><![CDATA[how to]]></category>
		<category><![CDATA[LDAP]]></category>
		<category><![CDATA[MVC]]></category>

		<guid isPermaLink="false">http://www.cmjackson.net/?p=262</guid>
		<description><![CDATA[If you are using ASP.NET MVC and you want to authenticate your users against Active Directory using LDAP, you need to do a little work to get everything set up. It is pretty easy to authenticate users with Active Directory using the &#60;Authorize()&#62; attribute, but I ran into some problems when I wanted to authorize [...]]]></description>
			<content:encoded><![CDATA[<p>If you are using ASP.NET MVC and you want to authenticate your users against Active Directory using LDAP, you need to do a little work to get everything set up. It is pretty easy to authenticate users with Active Directory using the &lt;Authorize()&gt; attribute, but I ran into some problems when I wanted to authorize a user based on a Windows Group.</p>
<p>Here are the steps I took to be able to authenticate active directory users and authorize their use of actions based on being members to user groups.</p>
<h3>Web.Config</h3>
<p>Find the authentication tag and change it to the following:</p>
<pre class="brush: xml;">
&lt;authentication mode=&quot;Forms&quot;&gt;
  &lt;forms loginUrl=&quot;~/Account/LogOn&quot; timeout=&quot;2880&quot; /&gt;
&lt;/authentication&gt;
</pre>
<p>The LoginUrl points to the Controller/Action where the login function is.</p>
<h3>UserRepository</h3>
<p>This is the class object that does the communication with Active Directory via LDAP. The project where this class resides should also add a reference to the System.DirectoryServices DLL.</p>
<pre class="brush: vb;">
Imports System.DirectoryServices

Public Class UserRepository

  Private _server As String

  Public Sub New(ByVal server As String)

    _server = server

  End Sub

  Public Function GetUser(ByVal userName As String) As Data.User

    Dim root As DirectoryEntry = New DirectoryEntry(&quot;LDAP://&quot; + _server)
    Dim search As DirectorySearcher = New DirectorySearcher(root)

    search.SearchScope = SearchScope.Subtree
    search.Filter = &quot;(sAMAccountName=&quot; + userName.Substring(userName.IndexOf(&quot;\&quot;) + 1) + &quot;)&quot;

    Dim results As SearchResultCollection = search.FindAll()

    Return _GetUser(results(0).Path)

  End Function

  Public Function GetUserByFullName(ByVal fullName As String) As Data.User

    Dim root As DirectoryEntry = New DirectoryEntry(&quot;LDAP://&quot; + _server)
    Dim search As DirectorySearcher = New DirectorySearcher(root)

    search.SearchScope = SearchScope.Subtree
    search.Filter = &quot;(displayName=&quot; + fullName + &quot;)&quot;

    Dim results As SearchResultCollection = search.FindAll()

    Return _GetUser(results(0).Path)

  End Function

  Public Function GetMembers(ByVal groupPath As String) As IQueryable(Of Data.User)

    Dim root As DirectoryEntry = New DirectoryEntry(&quot;LDAP://&quot; + _server)
    Dim search As DirectorySearcher = New DirectorySearcher(root)
    Dim members As List(Of Data.User) = New List(Of Data.User)()

    search.SearchScope = SearchScope.Subtree
    search.Filter = &quot;(memberOf=&quot; + groupPath + &quot;)&quot;

    Dim results As SearchResultCollection = search.FindAll()

    For Each result As SearchResult In results
      members.Add(_GetUser(result.Path))
    Next

    root.Close()

    Return members.AsQueryable

  End Function

  Public Function Authenticate(ByVal userName As String, ByVal password As String) As Data.User

    Dim root As DirectoryEntry = New DirectoryEntry(&quot;LDAP://&quot; + _server, userName, password)
    Dim search As DirectorySearcher = New DirectorySearcher(root)
    Dim user As User = Nothing

    search.SearchScope = SearchScope.Subtree
    search.Filter = &quot;(sAMAccountName=&quot; + userName + &quot;)&quot;

    Dim results As SearchResultCollection = search.FindAll()

    If (Not (results Is Nothing)) Then

        user = _GetUser(results(0).Path)

    End If

    Return user

  End Function

  Private Function _GetUser(ByVal userPath As String) As Data.User

    Dim entry As DirectoryEntry = New DirectoryEntry(userPath)
    Dim user As Data.User = New Data.User()

    user.UserName = entry.Properties(&quot;sAMAccountName&quot;).Value
    user.FirstName = entry.Properties(&quot;givenname&quot;).Value
    user.LastName = entry.Properties(&quot;sn&quot;).Value
    user.Email = entry.Properties(&quot;mail&quot;).Value

    For Each group In entry.Properties(&quot;memberOf&quot;)

        user.Groups.Add(_GetGroup(group))

    Next

    entry.Close()

    Return user

  End Function

  Private Function _GetGroup(ByVal path As String) As String

    Dim value As String = &quot;&quot;
    Dim index1 As Integer = path.IndexOf(&quot;=&quot;, 1)
    Dim index2 As Integer = path.IndexOf(&quot;,&quot;, 1)

    If (Not (index1 = -1)) Then

        value = path.Substring((index1 + 1), (index2 - index1) - 1)

    End If

    Return value

  End Function

End Class
</pre>
<h3>User</h3>
<p>This class hold the user information that we want to work with from Active Directory. Here I am storing the username, first and last names, email address, and the list of groups the user is a member of.</p>
<p>This class is in my Data project and that is why you will see Data.User in the UserRepository. If you want everything to be in one project, you could create the Data namespace around the User class. I did run into problems with MVC getting confused between my User class and a built in one if I did not specify the namespace. You could also simply rename the User class to something else.</p>
<pre class="brush: vb;">
Public Class User

    Private _userName As String
    Private _firstName As String
    Private _lastName As String
    Private _email As String
    Private _groups As List(Of String)

    Public Property UserName() As String
        Get
            Return _userName
        End Get
        Set(ByVal value As String)
            _userName = value
        End Set
    End Property

    Public Property FirstName() As String
        Get
            Return _firstName
        End Get
        Set(ByVal value As String)
            _firstName = value
        End Set
    End Property

    Public Property LastName() As String
        Get
            Return _lastName
        End Get
        Set(ByVal value As String)
            _lastName = value
        End Set
    End Property

    Public Property Email() As String
        Get
            Return _email
        End Get
        Set(ByVal value As String)
            _email = value
        End Set
    End Property

    Public Property Groups() As List(Of String)
        Get
            Return _groups
        End Get
        Set(ByVal value As List(Of String))
            _groups = value
        End Set
    End Property

    Public Sub New()

        Me.UserName = &quot;&quot;
        Me.FirstName = &quot;&quot;
        Me.LastName = &quot;&quot;
        Me.Email = &quot;&quot;

        Me.Groups = New List(Of String)()

    End Sub

    Public Function GetFullName() As String

        Dim s As System.Text.StringBuilder = New System.Text.StringBuilder()

        If (Not (Me.FirstName = &quot;&quot;)) Then

            s.Append(Me.FirstName)
            s.Append(&quot; &quot;)

        End If

        s.Append(Me.LastName)

        Return s.ToString()

    End Function

    Public Function SerializeGroups() As String

        Dim text As String = &quot;&quot;

        For Each item In Groups

            If (text = &quot;&quot;) Then

                text = item

            Else

                text = text + &quot;|&quot; + item

            End If

        Next

        Return text

    End Function

End Class
</pre>
<h3>AccountController</h3>
<p>Next is the controller that handles signing in and out of the application. I&#8217;ve simplified this controller code for the sake of simplicity. Under normal circumstances, I would have the controller communicate to a service class that then interacts with the repository. The service class could do validation on the login form before attempting to authenticate empty user and password strings.</p>
<pre class="brush: vb;">
Imports System.Globalization
Imports System.Security.Principal
Imports S3.Data

&lt;HandleError()&gt; _
Public Class AccountController
    Inherits System.Web.Mvc.Controller

    'data members.
    Private _userRepository as UserRepository
    Private _formsAuthentication As IFormsAuthentication

    Public Sub New()

        _userRepository = New UserRepository(ConfigurationManager.AppSettings(&quot;LDAPServer&quot;)
        _formsAuthentication = New FormsAuthentication()

    End Sub

    'GET: /Account/LogOn
    Public Function LogOn() As ActionResult

        Return View(&quot;LogOn&quot;)

    End Function

    'POST: /Account/LogOn
    &lt;AcceptVerbs(HttpVerbs.Post)&gt; _
    Public Function LogOn( _
        ByVal userName As String, _
        ByVal password As String, _
        ByVal rememberMe As Boolean, _
        ByVal returnUrl As String) As ActionResult

        Dim result As ActionResult = View(&quot;LogOn&quot;)
        Dim user As User = _userRepository.Authenticate(userName, password)

        If (Not (user Is Nothing)) Then

            _formsAuthentication.SignIn(user, rememberMe)

            If (returnUrl Is Nothing) Then

                result = RedirectToAction(&quot;Index&quot;, &quot;Home&quot;)

            Else

                result = Redirect(returnUrl)

            End If

        End If

        Return result

    End Function

    Public Function LogOff() As ActionResult

        _formsAuthentication.SignOut()
        Return RedirectToAction(&quot;Index&quot;, &quot;Home&quot;)

    End Function

End Class
</pre>
<h3>FormsAuthentication</h3>
<p>The next class is the FormsAuthentication class. The main reason that I made this code a class of its own is for the sake of unit testing my project. During unit testing, the commands that deal with writing and clearing the cookie would error out. To get around this, I created an empty FormsAuthenticationTest class that does nothing for the SignIn and SignOut methods. <strong>Note: The example code does not show the interfaces. Check out the repository pattern and factory pattern to see how to setup services and repositories for unit testing.</strong></p>
<p>After a user has been authenticated by the UserRepository, the controller passes the returned user into the SignIn method of the FormsAuthentication. This method then stores the user&#8217;s full name and serialized groups in a cookie. The list of groups is serialized by creating a string with each group name separated by a &#8220;|&#8221; character. This serialization takes place in the User object.</p>
<pre class="brush: vb;">
Imports System.Web.Security

Public Class FormsAuthentication

    Public Sub SignIn(ByVal user As Data.User, ByVal createPersistentCookie As Boolean)

        Dim authTicket As System.Web.Security.FormsAuthenticationTicket = _
            New System.Web.Security.FormsAuthenticationTicket( _
            1, _
            user.GetFullName(), _
            Now, _
            Now.AddMinutes(60), _
            createPersistentCookie, _
            user.SerializeGroups())

        Dim encryptedTicket As String = System.Web.Security.FormsAuthentication.Encrypt(authTicket)

        Dim authCookie As HttpCookie = New HttpCookie( _
            System.Web.Security.FormsAuthentication.FormsCookieName, _
            encryptedTicket)

        If (createPersistentCookie) Then

            authCookie.Expires = authTicket.Expiration

        End If

        HttpContext.Current.Response.Cookies.Add(authCookie)

    End Sub

    Public Sub SignOut()

        System.Web.Security.FormsAuthentication.SignOut()

    End Sub

End Class
</pre>
<h3>Global.asax</h3>
<p>With the previous code, you should be able to use Forms Authentication to log into your application and authenticate a user against the Active Directory via LDAP. The &lt;Authorize()&gt; attribute will allow you to secure your controller or actions. There&#8217;s just one problem. Now, if you want to use &lt;Authorize(Roles:=&#8221;GroupName&#8221;),  your user does not get authorization to the action or controller.</p>
<p>There&#8217;s just one change left that we need to make. ASP MVC makes the current logged in user available by accessing the Context.User. When you log into the application MVC is setting the user as authenticated, but no roles or groups have been added to that user. We need to modify the Global.asax file and use the AuthenticationRequest event.</p>
<p>The following code will fire each time an authentication request is triggered. The code will check if the authentication cookie exists and if it does, reads the user&#8217;s name and groups from it and stores them in the Context.User so MVC can access the groups.</p>
<pre class="brush: vb;">
    Private Sub MvcApplication_AuthenticateRequest(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.AuthenticateRequest

        Dim cookieName As String = System.Web.Security.FormsAuthentication.FormsCookieName
        Dim authCookie As HttpCookie = Context.Request.Cookies(cookieName)

        If (Not (authCookie Is Nothing)) Then

            Dim authTicket As System.Web.Security.FormsAuthenticationTicket = Nothing

            Try

                authTicket = System.Web.Security.FormsAuthentication.Decrypt(authCookie.Value)

                If (Not (authTicket Is Nothing)) Then

                    Dim groups As String() = authTicket.UserData.Split(New Char() {&quot;|&quot;})
                    Dim id As System.Security.Principal.GenericIdentity = _
                        New System.Security.Principal.GenericIdentity(authTicket.Name, &quot;LdapAuthentication&quot;)
                    Dim principal As System.Security.Principal.GenericPrincipal = _
                        New System.Security.Principal.GenericPrincipal(id, groups)

                    Context.User = principal

                End If

            Catch ex As Exception

                'Do nothing.

            End Try

        End If

    End Sub
</pre>
<p>And that should be all you need to use FormsAuthentication with LDAP and group authorization.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.cmjackson.net/2009/10/23/asp-net-mvc-using-forms-authentication-with-ldap/feed/</wfw:commentRss>
		<slash:comments>20</slash:comments>
		</item>
		<item>
		<title>How to setup CodeIgniter</title>
		<link>http://www.cmjackson.net/2009/06/30/how-to-setup-codeigniter/</link>
		<comments>http://www.cmjackson.net/2009/06/30/how-to-setup-codeigniter/#comments</comments>
		<pubDate>Wed, 01 Jul 2009 01:04:40 +0000</pubDate>
		<dc:creator>Chris Jackson</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Tutorial]]></category>
		<category><![CDATA[CodeIgniter]]></category>
		<category><![CDATA[how to]]></category>
		<category><![CDATA[MVC]]></category>
		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://www.cmjackson.net/?p=243</guid>
		<description><![CDATA[Introduction This article explains the process I go through to setup the CodeIgniter framework and how to configure it so that I can start developing an application. What is CodeIgniter? If you don&#8217;t already know, CodeIgniter is an MVC framework built on PHP.  There are many features and built in functions that make building a web [...]]]></description>
			<content:encoded><![CDATA[<h2>Introduction</h2>
<p>This article explains the process I go through to setup the CodeIgniter framework and how to configure it so that I can start developing an application.</p>
<h2>What is CodeIgniter?</h2>
<p>If you don&#8217;t already know, CodeIgniter is an MVC framework built on PHP.  There are many features and built in functions that make building a web application fairly easy.  You can download the current version, 1.7.1, from <a href="http://codeigniter.com/">CodeIgniter.com</a>.  Also, check out the very well documented <a href="http://codeigniter.com/user_guide/">User Guide</a>.</p>
<p>If you are interested in using the Zend library of tools with CodeIgniter, please check out <a href="http://www.cmjackson.net/2009/02/17/how-to-use-zend_search_lucene-with-the-php-framework-codeigniter/">How to use Zend_Search_Lucene with CodeIgniter</a>.</p>
<h2>Step-By-Step</h2>
<p>For this tutorial, I&#8217;m using a <a href="http://www.wampserver.com/">WAMP Server</a> running on my local Windows computer.  You could just as easily perform these same actions on a web server running PHP, although the paths may be different depending on if you are using Windows or a Linux based server.</p>
<h3>Step 1</h3>
<p>Download the latest version of <a href="http://codeigniter.com/download.php">CodeIgniter</a> (1.7.1).</p>
<p>Before extracting the files to your server, let&#8217;s talk about where to put the files.  For security purposes, it is recommended to place the CodeIgniter files outside the path of your web server so those files cannot be accessed by typing in a URL.  So, if I access my web server by typing in <a href="http://localhost">http://localhost</a> and the web server loads the website at C:\wamp\www\, then I want to place the System folder of CodeIgniter inside the C:\wamp\ folder.  Go ahead and extract the System folder from the download package to the C:\wamp\ folder.  You can place the System folder in the C:\wamp\www\ folder if you desire.  Just make sure to adjust the path name later on.</p>
<h3>Step 2</h3>
<p>Next, I have decided that I may want to use CodeIgniter for several applications that I develop.  To save on hosting space, I can setup all CodeIgniter applications to use the same core framework.  First, we need to move some files around from their default locations.</p>
<p>Open the C:\wamp\system\application\ folder.  You should see several folders listed here.  The default CodeIgniter application is setup for a single application.  We will be changing it to run multiple applications.  Create a new folder called baseApplication_1234 or something unique.  Make a copy of the index.html file and paste it inside baseApplication_1234.  Next, move all of the folders located at C:\wamp\system\application\ into C:\wamp\system\application\baseApplication_1234\.</p>
<p>We will configure this base application with all of our default settings that we want to use for all CodeIgniter applications.  Then, when you want to make a new application, you can simply copy the baseApplication_1234 and rename it.</p>
<h3>Step 3</h3>
<p>Next, we will configure the CodeIgniter application files.</p>
<p>Browse to C:\wamp\system\application\baseApplication_1234\config\ and open the following:</p>
<h4>autoload.php</h4>
<p>Modify line 42 to show:</p>
<pre class="brush: php;">$autoload['libraries'] = array('database', 'session');</pre>
<h4> config.php</h4>
<p>Modify line 14 to show (change localhost to your domain name):</p>
<pre class="brush: php;">$config['base_url'] = &quot;http://localhost/&quot;;</pre>
<p>Modify line 26 to show:</p>
<pre class="brush: php;">$config['index_page'] = &quot;index.php?&quot;;</pre>
<p>This line will be very important for the way our URLs are displayed later on.</p>
<p>Modify line 44 to show:</p>
<pre class="brush: php;">$config['uri_protocol'] = &quot;QUERY_STRING&quot;;</pre>
<p>Modify line 57 to show (this is optional if you want a .html to be shown on the end of your URLs):</p>
<pre class="brush: php;">$config['url_suffix'] = &quot;.html&quot;;</pre>
<p>Modify line 220 to show (add your own unique value within the quotes):</p>
<pre class="brush: php;">$config['encryption_key'] = &quot;12345&quot;;</pre>
<p>Modify lines 234 &#8211; 241 to show:</p>
<pre class="brush: php;">$config['sess_cookie_name']  = 'ci_session';
$config['sess_expiration']  = 7200;
$config['sess_encrypt_cookie'] = TRUE;
$config['sess_use_database'] = TRUE;
$config['sess_table_name']  = 'ci_sessions';
$config['sess_match_ip']  = TRUE;
$config['sess_match_useragent'] = TRUE;
$config['sess_time_to_update']  = 300;</pre>
<p>This will require that we have a database and a table within called ci_sessions.  This table will need to have certain fields that CodeIgniter will be attempting to write session data to for each users who visits your site.  I&#8217;ll explain more later on.</p>
<h4>database.php</h4>
<p>Modify lines 41 &#8211; 45 to show:</p>
<pre class="brush: php;">$db['default']['username'] = &quot;dbuser&quot;;
$db['default']['password'] = &quot;mypassword&quot;;
$db['default']['database'] = &quot;mydbname&quot;;
$db['default']['dbdriver'] = &quot;mysql&quot;;
$db['default']['dbprefix'] = &quot;dev_&quot;;</pre>
<p>You will need to enter your correct username, password, database name, and prefix if you wish to use one.  If you use a prefix, you will need to have a table called dev_ci_session instead of ci_session.</p>
<h4>routes.php</h4>
<p>For the base application, the routes.php file is probably OK.  There are two lines that need to be modified when you build an application. </p>
<pre class="brush: php;">$route['default_controller'] = &quot;welcome&quot;;
$route['scaffolding_trigger'] = &quot;12345&quot;;</pre>
<p>Again, use some unique value for the scaffolding_trigger.  If you use a value that is hackable or nothing at all, your application will have a possible security hole.  The default controller name can be changed here as well.</p>
<h3>Step 4</h3>
<p>There are two helper files that I add to my projects that help translate the URLs the way I like them (<a href="http://localhost/controller/action/id.html">http://localhost/controller/action/id.html</a>).</p>
<h4>MY_form_helper.php</h4>
<pre class="brush: php;">

&lt;?php  if ( ! defined('BASEPATH')) exit('No direct script access allowed');
if ( ! function_exists('form_open'))
{
    function form_open($action = '', $attributes = '', $hidden = array())
    {
        $CI =&amp; get_instance();

        if ($attributes == '')
        {
            $attributes = 'method=&quot;post&quot;';
        }

        //Modify -&gt;site_url to -&gt;item('base_url').$action
        $action = ( strpos($action, '://') === FALSE) ? $CI-&gt;config-&gt;item('base_url').$action : $action;

        $form = '&lt;form action=&quot;'.$action.'&quot;';
 
        $form .= _attributes_to_string($attributes, TRUE);
 
        $form .= '&gt;';

        if (is_array($hidden) AND count($hidden) &gt; 0)
        {
            $form .= form_hidden($hidden);
        }

        return $form;
    }
}
?&gt;</pre>
<h4>MY_url_helper.php</h4>
<pre class="brush: php;">

&lt;?php
function redirect($uri = '', $method = 'location', $http_response_code = 302)
{
    $CI =&amp; get_instance();

    switch($method)
    {
        case 'refresh' : header(&quot;Refresh:0;url=&quot;.site_url($uri));
        break;
        default   : header(&quot;Location: &quot;.$CI-&gt;config-&gt;item('base_url').$uri, TRUE, $http_response_code);
        break;
    }
    exit;
}
?&gt;</pre>
<p>Create these files and save them to C:\wamp\system\application\baseApplication_1234\helpers\.  These functions will override the original CodeIgniter functions and fix some URL rewriting issues.</p>
<h3>Step 5</h3>
<p>Enabling URL rewriting may depend if your server supports it.  Apache has a rewrite_module that must be enabled before this will work.  Most hosting providers should already have enabled URL rewriting.</p>
<p>Create a new text file called .htaccess and paste the following code into it:</p>
<pre>RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /index.php?$1 [L]</pre>
<p>This will redirect all requests on your domain back to the index.php file, unless the actual path does happen to exist, then the server will serve up whatever file/directory is at that location.</p>
<p>Notice the ? behind index.php.  The web server is rewriting the pretty URL into a QUERY_STRING that CodeIgniter is expecting and passes in the controller and action as variables such as index.php?var1=this&amp;var2=that. </p>
<p>The .htaccess file should be stored in the C:\wamp\www\ folder or the root of your web site.</p>
<h3>Step 6</h3>
<p>Next, the database will need to be created and the ci_sessions table created to store the user sessions to.</p>
<p>After you create the MySQL database, run the following SQL and it will create the table for you:</p>
<pre class="brush: sql;">CREATE TABLE `dev_ci_sessions` (
  `session_id` varchar(32) NOT NULL,
  `ip_address` varchar(15) NOT NULL,
  `user_agent` text NOT NULL,
  `last_activity` datetime NOT NULL,
  PRIMARY KEY  (`session_id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;</pre>
<p>Make sure to remove the &#8220;dev_&#8221; if you did not setup a dbprefix.</p>
<h3>Step 7</h3>
<p>Next, for testing purposes, we&#8217;ll setup the baseApplication_1234 web application and attempt to run it.</p>
<p>Find the index.php file that came with the CodeIgniter 1.7.1 download.  It should be located in the same folder as the system folder and user_guide folder.  Copy this file into your web site root at C:\wamp\www\.</p>
<p>Modify line 26 as shown:</p>
<pre class="brush: php;">$system_folder = &quot;c:/wamp/system&quot;;</pre>
<p>Modify line 43 as shown:</p>
<pre class="brush: php;">$application_folder = &quot;application/baseApplication_1234&quot;;</pre>
<p>This is the line that specifies which application to load.</p>
<p>This index.php file is the main entry point for the application.  It will use these modifications to find the C:\wamp\system\ folder and run the correct web application.  The only other files that need to be in the C:\wamp\www\ folder are files that HTML needs to be able to access via URLs such as images and JavaScript.</p>
<h3>Conclusion</h3>
<p>That should be everything.  You can now try to open your web application by going to the URL, <a href="http://localhost">http://localhost</a>.  The default controller is Welcome and the default action is Index, so you can also test <a href="http://localhost/welcome/index.html">http://localhost/welcome/index.html</a> to verify URL rewriting works.  Remember the &#8220;.html&#8221; can be used to hide that PHP is running your web site.  In reality, index is an action of the welcome controller and doesn&#8217;t need the &#8220;.html&#8221; to be there at all.</p>
<p>If you run into problems, you can add this line to an action or the controller&#8217;s constructor for further information:</p>
<pre class="brush: php;">$this-&gt;output-&gt;enable_profiler(TRUE);</pre>
<p>Be sure to shut this down when not needed, or it could give your users information you may not wish them to have.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.cmjackson.net/2009/06/30/how-to-setup-codeigniter/feed/</wfw:commentRss>
		<slash:comments>17</slash:comments>
		</item>
	</channel>
</rss>

