Apr 21, 2013

Search Functionality

A few common approaches to adding search functionality to a Web Application:

Web App Search Approaches

Pull down all of the data and then search on it using a for loop or LINQ - An approach I loathe because to me this is a waste of resources, especially if the content base you're pulling from is of a considerable amount. Just ask yourself, if you were at a library and you knew the topic you were looking for, would you pull out all of the books in the entire library and then filter down or simply find the topic's section and get the handful of books?

Implement a Stored Procedure with a query argument and return the results - An approach I have used over the years, it is easy to implement and for me it leaves the querying where it should be - in the database.

Creating a Search Class with a dynamic interface and customizable properties to search and a Stored Procedure backend like in Approach 2 - An approach I will be going down at a later date for site wide search of a very large/complex WebForms app.

For the scope of this project I am going with Option #2 since the scope of the content I am searching for only spans the Posts objects. At a later date in Phase 2 I will probably expand this to fit Option #3. However since I will want to be able to search on various objects and return them all in a meaningful way, fast and efficiently.
So let's dive into Option #2. Because the usage of virtually the same block of SQL is being utilized in many Stored Procedures at this point, I created a SQL View:
[sql]
CREATE VIEW dbo.ActivePosts
AS
SELECT
dbo.Posts.ID,
dbo.Posts.Created,
dbo.Posts.Title,
dbo.Posts.Body,
dbo.Users.Username,
dbo.Posts.URLSafename,
dbo.getTagsByPostFUNC(dbo.Posts.ID) AS 'TagList',
dbo.getSafeTagsByPostFUNC(dbo.Posts.ID) AS 'SafeTagList',
(SELECT COUNT(*) FROM dbo.PostComments WHERE dbo.PostComments.PostID = dbo.Posts.ID AND dbo.PostComments.Active = 1) AS 'NumComments'
FROM dbo.Posts
INNER JOIN dbo.Users ON
dbo.Users.ID = dbo.Posts.PostedByUserID
WHERE dbo.Posts.Active = 1
[/sql]
And then create a new Stored Procedures with the ability to search content and reference the new SQL View:
[sql]
CREATE PROCEDURE [dbo].[getSearchPostListingSP]
(@searchQueryString VARCHAR(MAX))
AS
SELECT
dbo.ActivePosts.*
FROM dbo.ActivePosts
WHERE
(dbo.ActivePosts.Title LIKE '%' + @searchQueryString + '%' OR
dbo.ActivePosts.Body LIKE '%' + @searchQueryString + '%')
ORDER BY dbo.ActivePosts.Created DESC
[/sql]
You may be asking why not simply add the ActivePosts SQL View to your Entity Model and do something like this in your C# code:

That's perfectly valid and I am not against doing it that, but I feel like code like that should be done at the Database level, thus the Stored Procedure. Granted Stored Procedures do add a level of maintenance over doing it via code. For one, anytime you update/add/remove columns you have to update the Complex Typein your Entity Model inside of Visual Studio and then update your C# code that makes reference to that Stored Procedure.
For me it is worth it, but to each their own. I have not made performance comparisons on this particular scenario, however last summer I did do some aggregate performance comparisons between LINQ, PLINQ and Stored Procedures in my in C#">LINQ vs PLINQ vs Stored Procedure Row Count Performance in C#. You can't do a 1 to 1 comparison between varchar column searching and aggregate function performance, but my point, or better put, my lesson I want to convey is to definitely keep an open mind and explore all possible routes. You never want to find yourself in a situation of stagnation in your software development career simply doing something because you know it works. Things change almost daily it seems - near impossible as a polyglot programmer to keep up with every change, but when a new project comes around at work do your homework even if it means sacrificing your nights and weekends. The benefits will become apparent instantly and for me the most rewarding aspect - knowing when you laid down that first character in your code you did so with the knowledge of what you were doing was the best you could provide to your employer and/or clients.
Back to implementing the Search functionality, I added the following function to my PostFactory class:

When all was done:
[caption id="attachment_2078" align="aligncenter" width="252"]in MVC App" width="252" height="171" class="size-full wp-image-2078" /> Search box in MVC App[/caption]
Now you might be asking, what if there are no results?
Your get an empty view:
[caption id="attachment_2079" align="aligncenter" width="300"] Empty Result - Wrong way to handle it[/caption]
This leads me to my next topic:

Custom Error Pages

We have all been on sites where we go some place we either don't have access to, doesn't exist anymore or we misspelled. WordPress had a fairly good handler for this scenario:
[caption id="attachment_2081" align="aligncenter" width="300"] WordPress Content not found Handler[/caption]
As seen above when no results are found, we want to let the user know, but also create a generic handler for other error events.
To get started let's add a Route to the Global.asax.cs:

Now you maybe asking why isn't the actual error going to be passed into the Controller to be displayed?
For me I personally feel a generic error message to the end user while logging/reporting the errors to administrators and maintainers of a site is the best approach. In addition, a generic message protects you somewhat from exposing sensitive information to a potential hacker such as "No users match the query" or worse off database connection information.
That being said I added a wrapper in my BaseController:

This wrapper will down the road record the error to the database and then email users with alerts turned on. Since I haven't started on the "admin" section I am leaving it as is for the time being. The reason for the argument being there currently is that so when that does happen all of my existing front end code is already good to go as far as logging.
Now that I've got my base function implemented, let's revisit the Search function mentioned earlier:

Optimization

You might be wondering why I left optimization for last? I feel as though premature optimization leads to not only a longer debugging period when nailing down initial functionality, but also if you do things right as you go on your optimizations are really just tweaking. I've done both approaches in my career and definitely have had more success with doing it last. If you've had the opposite experience please comment below, I would very much like to hear your story.
So where do I want to begin?

YSlow and MVC Bundling

For me it makes sense to do the more trivial checks that provide the most bang for the buck. A key tool to assist in this manner is YSlow. I personally use the Firefox Add-on version available here.
As with any optimization, you need to do a baseline check to give yourself a basis from which to improve. In this case I am going from a fully featured PHP based CMS, WordPress to a custom MVC4 Web App so I was very intrigued by the initial results below.
[caption id="attachment_2088" align="aligncenter" width="300"] WordPress YSlow Ratings[/caption]
[caption id="attachment_2089" align="aligncenter" width="300"] Custom MVC 4 App YSlow Ratings[/caption]
Only scoring 1 point less than the battle tested WordPress version with no optimizations I feel is pretty neat.
Let's now look into what YSlow marked the MVC 4 App down on.
In the first line item, it found that the site is using 13 JavaScript files and 8 CSS files. One of the neat MVC features is the idea of bundling multiple CSS and JavaScript files into one. This not only cuts down on the number of HTTP Requests, but also speeds up the initial page load where most of your content is subsequently cached on future page requests.
If you recall going back to an earlier post our _Layout.cshtml we included quite a few CSS and JavaScript files:

Now after re-running the YSlow test:
[caption id="attachment_2092" align="aligncenter" width="300"]in the MVC App" width="300" height="190" class="size-medium wp-image-2092" /> YSlow Ratings after Bundling of JavaScript Files in the MVC App[/caption]
Much improved, now we're rated better than WordPress itself. Now onto the bundling of the CSS styles.
Add the following below the previously added ScriptBundles in your BundleConfig class:

One thing that I should note is if your Bundling isn't working check your Routes. Because of my Routes, after deployment (and making sure the is set to false), I was getting 404 errors on my JavaScript and CSS Bundles.
My solution was to use the IgnoreRoutes method in my Global.asax.cs file:

MVC Caching

Now that we've reduced the amount of data being pushed out to the client and optimized the number of http requests, lets switch gears to reducing the load on the server and enhance the performance of your site.
Without diving into all of the intricacies of caching, I am going to turn on server side caching, specifically Output Caching. At a later date I will dive into other approaches of caching including the new HTML5 client side caching that I recently dove into.
That being said, turning on Output Caching in your MVC application is really easy, simply put the OutputCache Attribute above your ActionResults like so:

In this example, the ActionResult will be cached for one hour (3600 seconds = 1 hour) and by setting the VaryByParam to * that means each combination of arguments passed into the function is cached versus caching one argument combination and displaying the one result. I've seen developers simply turn on caching and not thinking about dynamic content - suffice it to say, think about what could be cached and what can't. Common items that don't change often like your header or sidebar can be cached without much thought, but think about User/Role specific content and how bad it would be for a "Guest" user to see content as a Admin because an Admin had accessed the page within the cache time before a Guest user had.

Conclusion

In this post I went through the last big three items left in my migration from WordPress to MVC: Search Handling, Custom Error Pages and Caching. That being said I have a few "polish" items to accomplish before switching over the site to all of the new code, namely additional testing and adding a basic admin section. After those items I will consider Phase 1 completed and go back to my Windows Phone projects.
Stay tuned for Post 9 tomorrow night with the polish items.

Apr 17, 2013

As mentioned yesterday I began diving back into a large project at work that involves Windows Workflow. At this point it had been almost six months to the day when I last touched the initial code I did, so today involved a lot of getting back into the mindset I had then and what I was trying to accomplish. This digging unfortunately left me figuring out I had left the code in a non-functional state, to the point that the Workflow Service was not connecting to the AppFabric databases properly. Long story short, three hours later I was able to get everything where I thought I had left it.
Lesson learned here is that before jumping projects, always make sure you leave it in a usable state or at least document what isn't working properly. In my defense, the original sidetracking project was to be only three weeks.
Back to the Windows Workflow development - one issue I was having today with my xamlx/Code Activity was my InArgument variables defined at a global level in my xamlx file I was not able to retrieve or set using the more proper method of:

No matter what, the value was always 0 when getting the variable's value even though it had been set on the entry point of the Workflow.
After trying virtually just about everything I could I came up with a work around that does work. Do note I highly doubt this is the way Microsoft intended for it to be accomplished, but for the time being this is the only way I could get my xamlx defined variables updated/set in the custom CodeActivity.
What I did was create as generic set/get functions as possible below:

Hopefully that gets someone on the right track and if you do eventually find the "correct" way please let me know. Otherwise I will definitely be asking the Windows Workflow experts at TechED North Americain June.

Apr 03, 2013

If you've been following my blog posts over the last couple of years you'll know I have a profound love of using XML files for reading and writing for various purposes. The files are small and because of things like Typed Datasetsin C# you can have clean interfaces to read and write XML files. In Windows Phone however, you do not have Typed Datasets so you're stuck utilizing the XmlSerializer to read and write. To make it a little easier going back to last Thanksgiving I wrote some helper classes in my NuGet library jcWPLIBRARY. The end result within a few lines you can read and write List Collections of Class Objects of your choosing. So why continue down this path?
Simple answer: I wanted it better.
Tonight I embarked on a "Version 2" of this functionality that really makes it easy to keep with your existing Entity Framework knowledge, but provide the functionality of a database on a Windows Phone 8 device that currently doesn't exist in the same vain it can in a MVC, WinForm, WebForm or Console app.
To make this even more of a learning experience, I plan to blog the entire process, the first part of the project: reading all of the objects from an existing file.
To begin, I am going to utilize the existing XmlHandlerclass in my existing Library. This code has been battle tested and I feel no need to write something from scratch especially since I am going to leave the existing classes in the library to not break anyone's apps or my own.
First thoughts, what does a XmlSerializer file actually look like when written to?
Let's assume you have the following class, a pretty basic class:

The output of the file is like so:
[xml]
<?xml version="1.0" encoding="utf-8"?>
<ArrayOfTest xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Test>
<ID>1</ID>
<Active>true</Active>
<Name>Testing Name</Name>
<Created>2013-04-03T20:47:09.8491958-04:00</Created>
</Test>
</ArrayOfTest>
[/xml]
I often forget the XmlSerializer uses the "ArrayOf" prefix on the name of the root object so when testing with sample data when writing a new Windows Phone 8 app I have to refer back - hopefully that helps someone out.
Going back to the task at hand - reading data from an XML file and providing an "Entity Framework" like experience - that requires a custom LINQ Provider and another day of programming it.
Stay tuned for Part 2 where I go over creating a custom LINQ Provider bound to an XML File.

Feb 20, 2013

For the last 2.5 years I've been using the default MonoDevelop Web Reference in my MonoTouch applications for work, but it's come to the point where I really need and want to make use of the WCF features that I do in my Windows Phone applications.
Even with the newly released iOS Integration in Visual Studio 2012, you still have to generate the proxy class with the slsvcutil included with the Silverlight 3.0 SDK.
If you're like me, you probably don't have Version 3.0 of the Silverlight SDK, you can get it from Microsoft here.
When running the tool you might get the following error:
Error: An error occurred in the tool.
Error: Could not load file or assembly 'C:\Program Files (x86)\Microsoft Silverl
ight\5.1.10411.0\System.Runtime.Serialization.dll' or one of its dependencies. T
his assembly is built by a runtime newer than the currently loaded runtime and c
annot be loaded.
Basically the tool is incorrectly trying to pull the newer 4.0 or 5.0 Silverlight Assemblies, to make it easy, I created a config file to simply drop into your c:\Program Files (x86)\Microsoft SDKs\Silverlight\v3.0\Tools folder, you can download it here.
From a command line (remember the shortcut to hold shift down and right click in the folder to open a command prompt):
[caption id="attachment_1853" align="aligncenter" width="593"] Silverlight 3 WCF Proxy Generation[/caption]
Enter the following, assuming you want to create a proxy for a localhost WCF Service to your c:\tmp folder:
SlSvcUtil.exe http://localhost/Service.svc?wsdl /noconfig /d:c:\tmp
Though I should note, this will generate Array collections and not List or ObservableCollection collections.
If you want to generate your Operation Contracts with return types of those collections simply add for List Collections:/collectionType:System.Collections.Generic.List`1
or ObservableCollection:
/collectionType:System.Collections.ObjectModel.ObservableCollection`1

Feb 13, 2013

Came into a frustrating issue this morning with an app using MVMM in Windows Phone 7. I had a couple of textboxes, 2 with multi-line support and an Application Bar with a Save Icon. The idea being if you wanted to save your changes in the textboxes, tap the Save Icon and everything would save. Little did I know, the Textboxes only trigger an update to your binding when losing focus. So if the end user left the textbox focused, the trigger wouldn't occur and your save functionality in your View Model would not have the newly entered text.
A clean work around for this problem is to create a generic OnTextChangedevent handler function to trigger the update and then map that function to each of your textboxes.
Here's some sample code in my XAML file:

Jan 25, 2013

Working on a XNA/XAML game tonight I wanted to have a consistent UI experience between the XAML and XNA views. A key part of that was matching the Photoshop graphics and the in-game font. Having never used a TrueType Font (TTF) in Windows Phone 7.x I was curious how hard it would be to do in Windows Phone 8 where I have found many tasks to be streamlined. Unsurprisingly the process is pretty straight forward:

Copy your TrueType Font to your solution folder

Make sure the Build Actionis set to Content and Copy to Output Directory to Copy if newer

In your XAML then reference the TrueType Font in your XAML with the file path#font name like so:

Note you need to keep any spaces found in the font, if you aren't sure, double click on the font and make sure your XAML matches the what I've circled in red:
[caption id="attachment_1810" align="aligncenter" width="572"]in Windows 8" width="572" height="339" class="size-full wp-image-1810" /> TrueType Font Name in Windows 8[/caption]
Something weird I did find with a couple of TrueType Fonts I tried was some font creators put a space at the end. If you're like me that'll drive you nuts, especially when referencing the custom font multiple times in your XAML. If you find a case like that, download TTFEdit from source forge and trim the space off the end and save it.
If you follow those steps properly, you'll have your TTF in your Windows Phone 8 App:
[caption id="attachment_1805" align="aligncenter" width="480"]in Windows Phone 8" width="480" height="800" class="size-full wp-image-1805" /> TTF in Windows Phone 8[/caption]

Jul 15, 2012

Something I never understood why it wasn't part of the base TextBox control is the ability to override the GotFocus colors with an easy to use property, like FocusForeground or FocusBackground.
You could do something like this:

By default, the Background on a Focus event of a Windows Phone TextBox control sets it to White, so if you had White Text previously, upon entering Text, your Text would be invisible. The workaround above isn't pretty, nor handles the LostFocus property (ie to revert back to your normal colors after entering Text. If you have 2,3,4 or more TextBox controls, this could get tedious/clutter up your code.
My "fix", extending the TextBox Control:

Feb 25, 2012

After having used PLINQ and the Concurrent collections for nearly 2 months now, I can say without a doubt, it is definitely the way of the future. This last week I used it extensively in writing a WCF Service that manipulated a lot of data and needed to return it to an ASP.NET client very quickly. And on the flip side it needed to execute a lot of SQL Insertions based on business logic pretty quickly.
As of February 25th, 2012, I think the best approach to writing a data layer is:

Expose all Data Layer access through a WCF Service, ensuring a clear separation between UI and Data Layers

Use of ADO.NET Entity Models tied to SQL Stored Procedures that return Complex Types for objects rather doing a .Where(a => a.Active).ToList()

Process larger result sets with PLINQ, using Concurrent Collections (ie ConcurrentQueue or ConcurrentDictionary) and returning them to the Client (ASP.NET, WP7 etc)

Next step in my opinion would be to add in intelligent App Fabric caching like what Smarty Template Engine did for PHP. Just a clean way to cache pages, while providing flexible ways to invalidate the cache. I am so glad I found that back in 2006 when I was still doing a lot of PHP work.

Feb 25, 2012

Finally got around to replacing the 4 80mm 40 decibel fans in my Origin 300 this morning. The noise from this one server was enough to travel from the basement inside a rack all the way to the 3rd floor Master Bedroom. Suffice it to say, I definitely couldn't run the server 24/7. Hunting around on Amazon, I found these 80mm Cooler Master fans, not too bad price wise and still put out decent air flow.
[caption id="attachment_963" align="aligncenter" width="225" caption="New Cooler Master 80mm replacement fans for my SGI Origin 300"][/caption]
Prep for the swap:
[caption id="attachment_964" align="aligncenter" width="225" caption="My Quad R14k SGI Origin 300"][/caption]
The original fan in case someone needed a part number:
[caption id="attachment_965" align="aligncenter" width="225" caption="SGI Origin 300 Stock Fan"][/caption]
As I was swapping in the new fans, I realized the fan connector was not the standard ATX style.
Stock Connector:
[caption id="attachment_966" align="aligncenter" width="300" caption="Stock SGI Origin 300 Fan Connector"][/caption]
Versus the standard ATX connector:
[caption id="attachment_967" align="aligncenter" width="300" caption="Repacement Cooler Master Fan ATX Connector"][/caption]
Luckily the standard 4 pin Molex power connector for the 2 Ultra 160 drives is right next to the fans, so a little wiring job and voila:
[caption id="attachment_968" align="aligncenter" width="300" caption="SGI Origin 300 with replacement fans installed"][/caption]
Note, doing it this way will throw an error in the L1 Console and will shut your machine down. A way around it is to simply connect to the Origin 300 over a console connection and type:
env off.
This is dangerous though as the server will not shutdown automatically if a fan fails or the server overheats.
Having said that, it came to my attention that IRIX does not install a Serial/Terminal client by default. The common cu is on the IRIX 6.5 Foundation CD 1 disk. Turn on the Subsystems Only in the IRIX Software Manager and scroll down until you see it. Chances are you're not running a base 6.5 install so you'll also need the first disk of your overlays (6.5.30 Overlay CD 1 in my case) in order to install it to resolve the package conflicts.
After installing you may receive a "CONNECT FAILURE: NO DEVICES AVAILABLE".
Open up vi or your favorite text editor and open up /etc/uucp/Devices
Add in a line:
Direct ttyd2 - 38400 direct
Make sure the spaces are there.
You can also try setting it up via the Serial Manager under the System Manager application.
Afterwards, simply running:
cu -l /dev/ttyd2 -s38400
Allowed me into my L1 console to turn off environment monitoring. Then hit Control + D to get back into the PROM Monitor and hit "1" to start IRIX.