Posts
32
Comments
31
Trackbacks
0
Sunday, January 29, 2012
MVC4 slides and demo
Here are the slides and demo from the MVC 4 presentation given at the Central Ohio .NET Developers Group on 01/26/12. Thanks for everyone who came out!
posted @ Sunday, January 29, 2012 10:01 PM | Feedback (0)
Thursday, January 26, 2012
Speaking at CONDG

I will be speaking tonight at CONDG on the topic of mobile capabilities in the new release of ASP.NET MVC 4.  Leading EDJE is sponsoring the event and will be providing dinner.

posted @ Thursday, January 26, 2012 11:12 AM | Feedback (0)
Saturday, April 16, 2011
SharePoint 2010: Enable Developer Dashboard

The following stsadm command will enable the developer dashboard in SharePoint 2010

stsadm -o setproperty -pn developer-dashboard -pv on

To enable it only for OnDemand (recommended) use this

stsadm -o setproperty -pn developer-dashboard -pv ondemand

When set for OnDemand an icon will appear in the upper right hand corner of the SharePoint site.  Clicking it will toggle the dashboard on and off for a specific page and user.  The performance is significantly better than doing a blanket trace for all pages and users.  Also, only site collection administrators will see the toggle icon.

posted @ Saturday, April 16, 2011 7:49 PM | Feedback (0)
Sunday, March 20, 2011
WCF 4.0 Presentation Slides

Here are the slides from the March MOCSDUG presentation on WCF 4.0. The code samples I used were modified versions of Microsoft's WCF and WF Samples for .NET Framework 4.0

posted @ Sunday, March 20, 2011 10:47 PM | Feedback (3)
Wednesday, March 02, 2011
Speaking about WCF 4.0 at MOCSDUG

I will be speaking about the new features in WCF 4.0 at the the Mid-Ohio Connected Systems Developer User Group (MOCSDUG) tomorrow, 03/03/11.  Here are more details 

posted @ Wednesday, March 02, 2011 6:23 PM | Feedback (1)
Monday, April 19, 2010
AutoMapper

Well-architected SOA applications tend to have at least two representations of a domain object, a message contract used as an external interface and an entity used internally by the application.  The reason for having two different data structures is to enable loose coupling between internal application logic and the consuming clients.  For the developer, this means a line of code like the one below repeated for every property of a message contract

Entities.Customer.FirstName = DataContracst.Customer.FirstName

With AutoMapper the same can be achieved with two lines of code.  First the types must be associated.  For a web application putting the code in the Application_Start event of the global.asax will work.

Mapper.CreateMap<DataContracts.Customer, Entities.Customer>();

Once the types have been associated the following code will map an object of type DataContracts.Customer to Entities.Customer.

Mapper.Map(customerDataContract, customerEntity);

posted @ Monday, April 19, 2010 5:42 PM | Feedback (1)
Monday, November 09, 2009
Hornget

Now that open source tools are becoming more popular within the Microsoft development community, finding the latest releases and and dependencies can be a lot of work.  Hornget simplifies this search process.  It is a central repository of all the latest open source releases.  Currently the site has packages in the following categories: frameworks, ioc, loggers, mappers, mocks, orm, and web.

posted @ Monday, November 09, 2009 8:41 PM | Feedback (1)
Wednesday, September 30, 2009
Speaking at MOCSDUG
I will be speaking at the Mid-Ohio Connected Systems Developers User Group tomorrow.  Details can be found here
posted @ Wednesday, September 30, 2009 5:20 PM | Feedback (0)
Saturday, August 22, 2009
Execute Client Commands From ASP.NET
There are times when it is necessary to execute client code from an asp.net page.   A number of ways exist to go about this, but the following is the easiest way I have found since  it does not require installation of a browser plugin.  Instead it streams a .bat file response to the user for execution.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

public partial class _Default : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        string file = @"echo you are running a bat file
pause";

        Response.Clear();
        Response.AddHeader("Content-Length", file.Length.ToString());
        Response.AddHeader("Content-Disposition", "attachment; filename=test.bat");
        Response.ContentType = "application/octet-stream";
        Response.Write(file);
       
    }
}
posted @ Saturday, August 22, 2009 6:16 PM | Feedback (0)
Wednesday, July 08, 2009
Finding Broken Links
Broken links have always been an issue with websites and intranets, and with the pervasiveness of user-driven content the problem has only increased.   Xenu's Link Sleuth is a utility to remedy this.  It will crawl an entire site and create a report of all working and broken links.  It has the ability to verify "'links, images, frames, plug-ins, backgrounds, local image maps, style sheets, scripts and java applets".  The download page can be found here.
posted @ Wednesday, July 08, 2009 3:10 PM | Feedback (1)
Wednesday, June 17, 2009
Speaking at COSPUG
I will be speaking at the Central Ohio SharePoint User Group tomorrow from 5:30-7:00 PM.  The topic will be SharePoint Security.  Stop by if you are in the area and interested.
posted @ Wednesday, June 17, 2009 8:31 PM | Feedback (3)
Tuesday, May 19, 2009
SharePoint: Embed Web Parts Within Web Parts
This might seem obvious, but web parts can easily be embedded within other web parts.  The abstract web part class inherits from the System.Web.UI.WebControls.WebControl (Actually it inherits from System.Web.UI.WebControls.WebParts.Part which inherits from System.Web.UI.WebControls.Panel which inherits from System.Web.UI.WebControls.WebControl).  This allows web parts to be added to the control tree the way any other control is added.

this.Controls.Add(new YourCustomWebPartClass());
posted @ Tuesday, May 19, 2009 5:27 PM | Feedback (0)
Thursday, January 29, 2009
Populate Drop Down List With All SharePoint Sites

I recently wrote a SharePoint web part where a requirement was to populate a drop down list with all sites (SPWebs) of a site collection.  This is probably a very common scenario but the API didn’t support it easily.  Initially it looked very straightforward.  The site collection property exposes an AllWebs property which is an SPWebCollection of every site within the site collection.  Unfortunately, this will cause an Access Denied exception when accessed by any user not in the site collection administrators group, even if that user has access to every site in the collection.

Another approach was to use the GetSubWebsForCurrentUser method on the top level site object.  Unfortunately, this method does not retrieve the entire site tree, but only the child sites directly underneath the parent site.  The below function will recursively call the GetSubWebsForcurrentUser method for each sub site and bind the results to a drop down list.

private void RecursivelyPopulateDDLSites(DropDownList DDLSites, SPWebCollection Webs)
        {
            foreach (SPWeb web in Webs)
            {
                
               DDLSites.Items.Add(new ListItem(web.Title, web.ID.ToString()));
               if (web.GetSubwebsForCurrentUser().Count > 0)
               {
               RecursivelyPopulateDDLSites(DDLSites, web.GetSubwebsForCurrentUser());
               }

            }
            
        }
posted @ Thursday, January 29, 2009 6:12 PM | Feedback (1)
Wednesday, January 28, 2009
C# Encryption

The .net framework contains useful classes for encryption found in the System.Security.Cryptography namespace. Even though these classes shield the developer from the complexity of the encryption algorithms, there is still a significant amount of implementation detail to handle.  Under most scenarios, a developer simply wants a function that takes a clear text string as a parameter and returns an encrypted string.  The C# code for this function is below

public string EncryptString(string ClearText)
        {

            byte[] clearTextBytes = Encoding.UTF8.GetBytes(ClearText);

            System.Security.Cryptography.SymmetricAlgorithm rijn =  SymmetricAlgorithm.Create();

            MemoryStream ms = new MemoryStream();
            byte[] rgbIV = Encoding.ASCII.GetBytes("ryojvlzmdalyglrj"); 
            byte[] key = Encoding.ASCII.GetBytes("hcxilkqbbhczfeultgbskdmaunivmfuo"); 
            CryptoStream cs = new CryptoStream(ms, rijn.CreateEncryptor(key, rgbIV), 
	   CryptoStreamMode.Write);

            cs.Write(clearTextBytes, 0, clearTextBytes.Length);

            cs.Close();

            return Convert.ToBase64String(ms.ToArray());
        }

The function to go from an encrypted string to clear text will do everything in the function above but in the opposite order. 

private string DecryptString(string EncryptedText)
        {
            byte[] encryptedTextBytes = Convert.FromBase64String(EncryptedText);

            MemoryStream ms = new MemoryStream();

            System.Security.Cryptography.SymmetricAlgorithm rijn = SymmetricAlgorithm.Create();


            byte[] rgbIV = Encoding.ASCII.GetBytes("ryojvlzmdalyglrj"); 
            byte[] key = Encoding.ASCII.GetBytes("hcxilkqbbhczfeultgbskdmaunivmfuo"); 

            CryptoStream cs = new CryptoStream(ms, rijn.CreateDecryptor(key, rgbIV), 
            CryptoStreamMode.Write);

            cs.Write(encryptedTextBytes, 0, encryptedTextBytes.Length);

            cs.Close();

            return Encoding.UTF8.GetString(ms.ToArray());

        }

Be sure to replace the encryption keys I provided above with your own unique values.  This site is an easy way to generate random letters of a given length.  Also, note that the encryption type used above is symmetric t.  If you need an asymmetric or hash algorithm use the appropriate class within the Cryptography namespace.

posted @ Wednesday, January 28, 2009 8:15 PM | Feedback (6)
Tuesday, December 16, 2008
LINQ Error: Could not find an implementation of the query pattern for source type
If you receive an error like the following for a LINQ expression "Could not find an implementation of the query pattern for source type 'Microsoft.SharePoint.SPWebCollection'.  'Where' not found.  Consider explicitly specifying the type of the range variable" the reason is either that the object does not implement IEnumerable or that the compiler needs to be explicity told what to enumerate.  In the above case Microsoft.SharePoint.SPWebCollection is enumerable for type SPWeb so to fix the error the code needs to be modified from this

IEnumerable<SPWeb> webs = from web in SPContext.Current.Site.AllWebs where web.Permissions.DoesUserHavePermissions(SPRights.ViewListItems) select web;

To this

IEnumerable<SPWeb> webs = from SPWeb web in SPContext.Current.Site.AllWebs where web.Permissions.DoesUserHavePermissions(SPRights.ViewListItems) select web;
posted @ Tuesday, December 16, 2008 3:13 PM | Feedback (1)
Connect to Oracle with SSIS

Before connecting to an Oracle database from SSIS, there are two prerequisites that must be completed.  First, the client drivers must be installed on the server running the SSIS package.  Secondly, the tnsnames.ora configuration file must be set up with the appropriate connection information.


There are many client drivers that correspond to different versions of the Oracle database server and the client OS.  They can be downloaded here from the Oracle website (registration required).  Once the drivers have been downloaded and extracted, installation can begin by running setup.exe.  On the select installation type, the Runtime or Administrator option should be selected.  After selecting a file location the drivers will install on the system.  Assuming setup completes successfully, the tnsnames.ora file is ready to be modified.
The TNSNAMES.ora file instructs the oracle driver where and how to connect to an Oracle Database.  Under the default installation file path, a sample TNSNAMES.ora file can be found C:\oracle\product\[database version]\client_1\network\ADMIN\SAMPLE.  However, the actual TNSNAMES.ora should be place one directory up in the ADMIN folder.  For more information on TNSNAMES refer to the Oracle documentation


With the above steps completed the connection can now be established from within SSIS.  Because the OLE DB Source and Destination shapes rely on OLE DB Connections, the connection must first be created.  To complete this, right click on the Connection Manager pane and Select New OLE DB Connection.   In the provider drop down list select Oracle Provider for OLE DB.  In the Server or file name textbox enter the connection name defined in your tnsnames.ora file.  Finally, enter your username and password and click Test Connection.


If the connection is not successful the TNSPing utility can be used to troubleshoot any issues.  It can be found default file location is C:\oracle\product\[database version\client_1\bin.

posted @ Tuesday, December 16, 2008 1:14 AM | Feedback (1)
Friday, November 28, 2008
Visual Studio 2008 Default Keyboard Shortcuts

Knowing the IDE keyboard shortcuts is one of the easiest ways to increase coding productivity.  Think about how much of a bottleneck the mouse can be.  It uses 4 commands:  horizontal movement, vertical movement, left click, and right click.  Communicating with a complex editor with these four commands is like trying to chop down a tree with just one hand.  Here is a reference of the most commonly used keybindings for Visual Studio 2008.  However, these are only the defaults.  You can customize your environment from the Tools > Options > Envrionment > Keyboard screen.

posted @ Friday, November 28, 2008 10:38 PM | Feedback (0)
Wednesday, October 01, 2008
SharePoint: Edit Page missing from Dispform.aspx

You may notice the Edit Page option missing from the Site Actions menu on pages that use the list item templates (by default they are AllItems.aspx, EditForm.aspx, NewForm.aspx, DispForm.aspx).  First, make sure you have a web part zone on the page.  The site actions won't display Edit Page option if the page doesn't contain a single zone.

<WebPartPages:WebPartZone runat="server" Frametype="TitleBarOnly" id="Zone1" Title="loc:Right"><ZomeTemplate></ZomeTemplate></WebPartPages:WebPartZone>

However, even with the zone, the Edit Page option doesn't always appear.  This is a bug with SharePoint.  A workaround is to make sure the page contains at least one web part.  You can do this in SharePoint Designer by clicking on the "Click to insert a Web Part" link inside the webpart zone and then dragging a web part from the Web Part List menu.

posted @ Wednesday, October 01, 2008 3:22 PM | Feedback (1)
Saturday, August 02, 2008
Slow Performance in SSIS with SQL FOR XML Clause
SQL Server Integration Services has a significant performance issue with large result sets returned by SQL'ss FOR XML clause.  The problem is due to memory consumption and the way SSIS's data flow engine handles row-based results.  When SSIS receives a data stream, it buffers a portion of the stream, performs the necessary operations on the rows in the buffer, clears the buffer, and repeats the process until there is no more data remaining in the stream. The problem with the way FOR XML returns data is that it doesn't return rows, but rather a result set with a single row, which is seen by SSIS as a large Binary Large Object ( BLOB).

The initial reaction many developers have to this issue is to decrease the DefaultBufferSize property of data flow task.  Unfortunately, this won't help at all since the buffer is not able work with fractional rows, which means the buffer(s) will continue to fill beyond their threshold until a whole number of rows is reached. With a single row, this means the entire stream will be loaded into memory.  SQL 2005 and above provide a solution to this problem with the ability to shred the xml data type into individual rows.  Compare the result returned by the below queries.
DECLARE @XML xml

SET @XML = (SELECT
UserID,
FirstName,
LastName
FROM
Users
FOR XML PATH('User'))
SELECT @XML AS UserXML
results with a single row
DECLARE @XML xml

SET @XML = (SELECT
UserID,
FirstName,
LastName
FROM
Users
FOR XML PATH('User'))


SELECT nref.query('.') AS UserXML
from @XML.nodes('//User') AS R(nref)
results with multiple rows SSIS can efficiently buffer the result set returned by the second query, which will enable large sets to be processed without issue.
posted @ Saturday, August 02, 2008 7:54 PM | Feedback (1)
Thursday, July 24, 2008
Search Server 2008 Express in a WSS 3.0 Farm

If you receive the following error on a front-end web server of a WSS 3.0 farm while performing a search against Search Server 2008

Object reference not set to an instance of an object.   at Microsoft.Office.Server.Search.WebControls.CoreResultsWebPart.OnLoad(EventArgs e)
   at System.Web.UI.Control.LoadRecursive()
   at System.Web.UI.Control.LoadRecursive()
   at System.Web.UI.Control.LoadRecursive()
   at System.Web.UI.Control.LoadRecursive()
   at System.Web.UI.Control.LoadRecursive()
   at System.Web.UI.Control.LoadRecursive()
   at System.Web.UI.Control.LoadRecursive()
   at System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)

First make sure you have the front-end web server component of Search Server 2008 installed on the server where you are performing the search.  Next, add the URL you are using to access the server in your alternate access mappings.  Within Central Administration, navigate to Operations -> Global Configuration -> Alternate Access Mappings.  "Select Add Internal URLs".  Select your web application in the Alternate Access Mapping Collection drop down list.  Specify the path and port you use to access the application (example:  http://machinename01:80).  Click Save.  There is no need for an IIS reset.  The change should immediately take effect .

posted @ Thursday, July 24, 2008 6:40 PM | Feedback (2)
Wednesday, July 02, 2008
Comma Delimited Parameters In Stored Procedure
A scenario I've repeatedly encountered in database development is to create a stored procedure that accepts a range of values as a comma delimited list and returns a result set that contains at least one of the values from the list.  To do this, the parameter value must be parsed as something that can be understood by the IN clause.  I prefer to turn the delimited list into a single tabled column.  Because this task is so common, I wrote the following function that takes a comma delimited string and returns a table variable.
CREATE FUNCTION [dbo].[fnCommaDelimitedToTable]
(
@CommaDelimited varchar(5000)
)
RETURNS @returntable TABLE
(
FilterColumn varchar(50)
)
AS
BEGIN
SET @CommaDelimited = REPLACE(@CommaDelimited, ', ', ',')
WHILE CHARINDEX(',' , @CommaDelimited) > 0
BEGIN
INSERT INTO
@returntable
VALUES
(
SUBSTRING(@CommaDelimited, 0, CHARINDEX(',', @CommaDelimited))
)

SET @CommaDelimited = SUBSTRING(@CommaDelimited, CHARINDEX(',', @CommaDelimited) + 1,
LEN(@CommaDelimited))
END
-- Insert the last one, or if there was only one supplied.
INSERT INTO
@returntable
VALUES
(
@CommaDelimited
)
RETURN
END
With this function you can now write queries like
SELECT *
FROM
Customers
WHERE
Name IN (SELECT SearchFilter FROM dbo.fnCommaDelimitedToTable(@DelimitedNames))
posted @ Wednesday, July 02, 2008 2:55 AM | Feedback (0)
Tuesday, June 24, 2008
SSIS DataReader Source and BlobColumn

In SQL Server Integration Services (SSIS) the DataReader Source component is analogous to ADO.NET's DataReader classes.  It retrieves a Binary Large Object (BLOB) stream from the data source and is therefore efficient and the least expensive option in terms of memory.  Having said that, there are times when it is convenient to convert the returned BlobColumn into a string object.  Within a script component, the following will build a binary array from the BLOB stream and then encode the binary array to a Unicode string.

Dim result As String = _
System.Text.Encoding.Unicode.GetString(Row.FieldName.GetBlobData(0, CInt(Row.FieldName.Length)))

Again, one should be cautious when doing this.  It is similar to using the DataAdapter class to convert a DataReader to a DataSet, so depending on the size of the data, this may or may not be a good idea.

posted @ Tuesday, June 24, 2008 1:27 PM | Feedback (1)
Monday, April 28, 2008
Visual Studio 2008 For Free

Microsoft is offereing Visual Studio 2008 along with Windows Server 2003, Expression Studio, and XNA game studio at no cost to college students.  Visit the Microsoft DreamSpark site to register and download .  Enjoy.

posted @ Monday, April 28, 2008 6:32 PM | Feedback (1)
Saturday, April 12, 2008
Disable Days on ASP.NET Calendar Control
Disabling a range of dates on a calendar control is a great way to reduce data-entry error.  For example, imagine a scheduling system for an organization whose doors are open Monday through Friday.  Ideally, any calendar controls should disable Saturday and Sunday to prevent users from accidentally choosing them.  This can be accomplished by taking advantage of the ondayrender event of the calendar control.  First, in your aspx  markup, wire up a method to the event.

<asp:Calendar Visible="false" ID="DisabledWeekendsCalendar" runat="server" ondayrender="DisabledWeekendsCalendar_DayRender"></asp:Calendar>

Finally, in your .NET code, create the method which checks to see if a day is a weekend, and if so disables it.

protected void DisabledWeekendsCalendar_DayRender(object sender, DayRenderEventArgs e)
    {
        if (e.Day.Date.DayOfWeek == DayOfWeek.Saturday || e.Day.Date.DayOfWeek == DayOfWeek.Sunday)
        {
            e.Day.IsSelectable = false;
            e.Cell.ForeColor = System.Drawing.Color.Gray;
        }
    }

posted @ Saturday, April 12, 2008 4:28 PM | Feedback (2)
Tuesday, April 01, 2008
Paging with SQL Server 2000

With Microsoft SQL Server 2005, paging on the database side is simple.  There is a built-in ROW_NUMBER function designed specifically for this task.  However, versions of SQL Server prior to 2005 do not have this capability.  Below is one way to implement similar functionality in pre-2005 versions. 

SELECT 
TOP X *
FROM
Records
WHERE
RecordID NOT IN (SELECT TOP Y RecordID FROM Records)

You must replace X and Y with actual integer values, Unfortuantly, due to sql sytanx, you can’t use varaibles.  The records returned from the above query will follow

Y + 1 = Beginning record
X + Y + 1 = Ending Record

So 10 and 20 plugged in to X and Y respectively would return records 21 thorugh 31.

posted @ Tuesday, April 01, 2008 9:23 PM | Feedback (1)