Tuesday, December 31, 2013

Disabling ASP LinkButton controls in newer versions of Internet Explorer

Since IE 10, I have noticed that when a LinkButton control is disabled (Enabled="False"), the rendered link is not grayed out like it used to be and seemingly should be.  The link is disabled for all intents and purposes, but just appears to be enabled.  This can cause confusion to users if you rely on this mechanism.  The quick fix has always been "compatibility view" in IE, but this is being phased out over time by Microsoft as we get newer version of Internet Explorer.

Interestingly enough, the html rendered is the same.  You still get an anchor tag with the disabled attribute set to "disabled".  It is the browser that is reacting differently to this tag.  IE no longer styles by default an anchor tag with this particular attribute the way you expect (i.e. "grayed out").  You are forced to provide the css to render in this scenario.  The following css should style your LinkButton like the good ole days.
    a[disabled="disabled"] {
        color: gray;
        text-decoration: none;
    }
    a[disabled="disabled"]:hover {
        color: gray;
        text-decoration: none;
    }
Now, maybe you can finally turn off compatibility view!

Thursday, December 26, 2013

Debug .NET web applications without timing out

This happens when you are hosting the web application in IIS.  Just open up IIS, click on the application pool and go to Advanced Settings.  Set Ping Enabled to False.  Apparently IIS pings itself occasionally and if it doesn't get a response, then it shuts down.  Keep in mind that while you are debugging, IIS is blocking all other requests, so it sees this as a bad thing.  So turning this behavior off during development is fine.

Friday, December 20, 2013

Manage file extensions served by a web server

If your web site exposes files for users to open, and certain file types open and certain file types don't, then you will need to add the extensions that aren't working to the MIME Types associated with the site in IIS.

  1. Open up IIS
  2. Select the Site, and choose MIME Types in the IIS section.
  3. Click on Add, and add the extension.

A quick google search should obtain the MIME Type for the extension you want to add.

Simple and secure exception handling for .NET web applications

It is best practice not to display details of an exception on the page visible to anyone.  To hide these details, simply add the following to your web.config.
<configuration>
  <system.web>
    <customErrors mode="On" defaultRedirect="WebPages/ErrorPage.aspx"></customErrors>
  </system.web>
</configuration>
You can also change the mode attribute to "RemoteOnly" to only hide errors if viewing the site on a machine other than the web server.  The redirect simply takes the users to a page other than the "yellow screen of death" page that ASP provides.

It is also imperative to add a Global.asax file to your web application project.  You'll want to log anything that fires off the Application_Error event since these represent any unhandled exceptions and the details will no longer be visible on the screen.  Something like this will accomplish that:
Sub Application_Error(ByVal sender As Object, ByVal e As EventArgs)
    ' Fires when an error occurs

    Dim MyException As Exception = Server.GetLastError()

    ' Log the exception details here.
End Sub

Tuesday, December 17, 2013

Show or Hide the login window when accessing a site that uses Windows Authentication.

You're working on a site that is set up for Windows Authentication.  Two scenarios:

  1. You want your credentials to "pass through" without logging in.  In IE, open Internet Options, Security tab.  Select the zone the site is in, or add it to a zone if appropriate.  Click the Custom Level button.  Scroll down and select the "Automatic logon with current username and password" under the User Authentication, Logon section.
  2. You don't want to be logged in automatically so you can log in as other people for testing or whatever.  Follow the steps above except choose the "Prompt for username and password" radio button.

Wednesday, December 11, 2013

Implementing Windows Authentication

Windows authentication essentially means you are letting users into your web site if they have a valid AD user id and password in a specified group.  It is simple and works great for an intranet application.  It's important to note that IIS is responsible for the actual authentication.  So first, you need to enable Windows Authentication for the site.  To accomplish this:
  1. Open IIS.
  2. Select the site.
  3. Click "Authentication" in the IIS group.
  4. Disable "Anonymous Authentication"
  5. Enable "Windows Authentication"
It's possible that Windows Authentication has not been installed on the web server.  If this is the case, you will need to enable that feature through the control panel.

At this point, when a user browses to your site, the browser will see that anonymous authentication is disabled and will display a login box because of the windows authentication.  Once, the user authenticates, IIS sends the user information to the actual web application.  At this point, it is up to the web application to authorize the user.  

This authorization is configured in your web.config.  Here is an example that restricts access to users in a certain AD group:
<configuration>
    <system.web>
        <authentication mode="Windows" />
        <authorization>
            <allow roles="PowerUsers" />
            <deny users="*" />
        </authorization>
    </system.web>
</configuration>
Remember that the allow element takes precedence of the deny element.

To get the user name on an aspx page, simply type User.Identity.Name.  To get the user name in .net server side code, use the fully qualified System.Web.HttpContext.Current.User.Identity.Name.

Wednesday, December 4, 2013

Eclipse "intellisense"

Intellisense is actually a Microsoft term for autocompletion functionality in Visual Studio while writing code.  However, Eclipse offers the same feature for Java and Android development.  It's called method selection helper or something like that.  Anyway, it pops up automatically by default but disappears after you select something or type over what it suggests.  To get it back, just use the shortcut key combination of ctrl-space.

Monday, November 25, 2013

Grouping with Linq

Linq offers pretty much the same aggregate functions that SQL does.  And like SQL, often times you want to group results together when aggregating.  Grouping is a little less intuitive with Linq especially when using VB to write your queries.  Here is an example:

Dim MostRecentByCategory = (
    From mt In MyTable
    Group mt By mt.CategoryId Into g = Group
    Select CategoryId, MostRecentDate = g.Max(Function(mt) mt.CreatedDate) )

In our example, we have a table called MyTable. Each record has a category specified by a CategoryId field. If you wanted the most recent date that a record was created in each category, this query should do the trick. Of course, this is not real practical. More than likely, you are going to want the whole record. In other words, you're going to want a result set that represents the most recent record for each category (not just the date). As far as I know, this cannot be accomplished in just one Linq query.  To accomplish this, I would just create a new linq query and join MyTable to the result set we just queried (on CreatedDate and CategoryId).

As far as I can tell, you can only group when a single table or result set exists in your query.  If you want to group across multiple tables, you'll need to join the tables in a result set and then group the single result set.

For example, let's say there is a table named Category and each record in that table has CategoryId and Description.  How can we group MyTable by CategoryId and display the description of each category?  First we need to join the tables in a result set like this:

Dim Records = ( _
    From a In MyTable
        Join b In Category
            On a.CategoryId Equals b.Category
    Select New With {.CategoryId = a.CategoryId, .CategoryDescription = b.Description})

Now, have a single result set with the field that we need (Description) in it.  Then group this result table like above:

Dim CountsByCategory = (
    From r In Records
    Group r By r.CategoryDescription Into g = Group
    Select CategoryDescription, NumberFound = g.Count() )

Shortcut to "Document is ready" code in jQuery

When you want to execute some jQuery you normally encapsulate the code inside one of these:
$(document).ready(function () {
    // Code that executes when document is ready.
});
However, when looking around at examples in the API documentation, you'll sometimes see this which apparently is equivalent:
$(function() {
    // Code that executes when document is ready.
});

Wednesday, November 13, 2013

ASP.NET View State

The "state" of a web page is the properties of the controls on the page.  When you do a post back, it is desirable to save this info if you are posting back to the same page.  For example, if you are just paging through a grid or something.  ASP just sticks the view state in a hidden input field named "__ViewState".

It is not stored in English though.  It is encoded using Base64.  However, since anyone can decode a Base64 string, the view state data is considered openly readable by anyone.  Plus, a malicious user could tamper with the view state to do something evil.  To deal with this, ASP will "hash" the view state and then store the result of the "hash" in the __ViewState field.  ASP runs the view state and the MAC (Machine Authentication Code) and runs them through a hashing algorithm to produce the hash value stored in the source.  Hashing the view state protects the view state from being tampered with.  However, the view state data can still be viewed even though it has been hashed.  Not sure how at the time of this writing, but apparently, it can be done.  Anyway, if there is something especially confidential in the view state you can encrypt it.

If you want to see what is in the __ViewState field, just run Fiddler and post a web page in a browser.  Look at the source and locate the __ViewState field.  Select the gobblygook, right click and sent it to the TextWizard.  Decode it from Base64 to see the data.  If it is still gobblygook, then it has been hashed or encrypted or both.  You'll need to turn off hashing and encrypting the view state.  You can do this in the web.config file by adding this inside the system.web node:
<pages viewStateEncryptionMode="Never" enableViewStateMac="false" ></pages>
Recently, I was told that some of our .net 2.0 applications were not encrypting the view state.  In fact, when I viewed it in Fiddler, it wasn't even hashed!  So I added this to the system.web node in the web.config file:
<pages viewStateEncryptionMode="Always" enableViewStateMac="true" ></pages>
Interestingly, I had to add this:
<machineKey validation="3DES" />
inside the system.web node as well.  I'm not sure why I had to do this on one site but not the other.  I the Machine Key section in IIS for the site was configured differently, but I'm not positive.  Just make sure the view state is actually being encrypted by using Fiddler.

It appears that the hashing and encryption of the view state is done by default in later versions of the .NET Framework.

Tuesday, November 12, 2013

HTTP, Fiddler, and Telnet

HTTP is the "language" that browsers (clients) use to communicate with web servers.  Browsers send "request" messages to the web server.  The web server sends back "response" messages to the browser.  Each message consists of:

  1. An initial line that summarizes the message.
  2. A "headers" section that contains helpful information about the message.
  3. The body of the message.

The intial line of a request contains the "verb".  HTTP consists of only a handful of verbs that tell the web server what kind of request they are making.  GET is the most popular request made by a browser.  The browser is requesting a particular resource (html, image, other file, etc.) which is specified in the initial line of the message by indicating its URL.

The intial line of a response contains a status code and a very short description.  For example, "HTTP/1.1 200 OK".  The body of a response contains the actual resource.  For example, it would contain the html if that is what was requested.

You can actually see these messages going back and forth with a little program called Fiddler.  Just download Fiddler, install it, and run it.  If you type in a URL in a browser, you will see the corresponding GET request message in Fiddler.  Click on the Inspectors tab to see the initial line and "headers".

If you want to see the response messages, you have to download an add on called Syntax Highlighting AddOns.  There should be a link below the box that displays the details of the request message.  Once you install this, add on, you can see the details of the response for each request.  Pretty cool.

Going a step further, you can make GET requests manually independent of a browser by using Telnet.  By default, in Windows 7, Telnet is not enabled.  You have to go into Control Panel and Add/Remove Windows Features.  Enable the Telnet Client.  Then, just open up a command prompt and type as an example:

Telnet localhost 3405

-Ctrl ]-

set localecho

-Enter-

-Enter again-

GET /test.html HTTP/1.1
Host: localhost

-Enter-

-Enter again-

Now you see the response message from the web server.

Pretty cool.

Here's a good link to some helpful (if a bit dated) info on HTTP:
http://www.jmarshall.com/easy/http/

Thursday, November 7, 2013

Be aware of binding peculiarities when posting a form more than once using MVC

Occasionally, you will find yourself in a situation where you might need to post more than once.  For example, when the form doesn't pass validation, the user is returned to the form, and must post again once they have made corrections.

You may want to change some fields on the page during this first post, so that when the user returns, he sees something different.  Or, you may want to set a hidden field to indicate something.  You cannot do this if the model field is bound to an element on the view.  It is important to understand that the model is bound to the element and only element.  If you are going to return to the view, you can't break this binding even if you set the field to something else in the action method.

If you absolutely need to do this, you can use JavaScript/jQuery connected to the submit button to set the field on the page.

Monday, October 28, 2013

Ignore the route when adding a web service to an MVC project

You may want to add a web service to an MVC project in order to to implement AJAX call backs.  Remember that MVC is always trying to interpret URLs using it's routing configuration.  So, if the routing configuration encounters a URL referring to your web service, the framework won't know what to do with it.

You could just put it into another web project.  This works fine with IE 10, but Chrome will blow up.  I think it has something to do with cross domain configuration (and lack thereof).  Do yourself a favor, and stick it in the MVC project, and remember to add this to your RegisterRoutes method:

routes.IgnoreRoute("YourAjaxEnabledService.svc/DoWork")

Thursday, October 24, 2013

Use a custom editor template when using a partial view to edit data.

Let's say your view is being used to edit some data.  Part of the data being edited appears elsewhere in the app and you might want to reuse it.  For example, an address.  There may be multiple places in your application where you want to have the ability to edit an address.  You might be tempted to just make a partial view and then render it within the parent view by doing something like this:

@Code
    Html.RenderPartial("Address", Model.MyAddressViewModel)
End Code

The problem is that this doesn't bind back to the parent model when the parent form is submitted. Use the Editor helper instead:

@Html.EditorFor(function(m) m.MyAddressViewModel)

Now this will bind. However, the resulting html looks like crap. You can either decorate the crap out of your view model, or just make a custom editor template. All you have to do is make a new folder called EditorTemplates in the Shared folder of your MVC project.  Then put the partial view in this folder.  Make sure you name the view the same as the data type of the object your are creating the editor for.  For example, AddressViewModel.vbhtml.

Friday, October 18, 2013

MVC Buttons, Links, and Actions

With any web page, you need to execute code on the server in response to user actions.  With traditional web forms, this was accomplished with event handlers generally tied to buttons, and links.  With MVC, we have this concept of an "action method".  So, the question becomes, how do we kick off action methods?  There are 3 big ways to do this:
  1. The user enters a url and the routing system kicks off the action method associated with the route.  The parameters of the action method are in the route itself, or exist as query parameters.  Technically this is a GET request.
  2. The user clicks a link defined by the Html.ActionLink method.  ActionLink will generate a url that contains the route necessary to execute the specified action method on the specified controller with the provided parameters.  Technically this is a GET request.
  3. Within a form element, the user clicks on a button with the "type" attribute set to "submit".  The action method associated with the form is executed.  Parameters are provided through model binding.  Technically this is a POST request.
One and Two are really doing the same thing.  So, we are either doing a GET with a link, or a POST with a button.  When do we use a GET link, and when do we use a POST button?

Standard practice is to use a GET link if we are not changing anything and POST button when are changing something.

What is model binding?  First of all model binding only occurs during a POST.  It's not going to happen if you are kicking off an action method through a link (such as creating one with Html.ActionLink).  Any parameters for the action method associated with the form will be automatically provided based on matching up the names of the ids on the page with the names of the parameters.  So if you have a hidden field with an id of "Price", and you have a parameter of your action method named "Price", this will automatically be sent to the action method when you POST.

Some people are fond of everything being a button, even stuff that shouldn't be a POST.  For example, a "Cancel" button.  One option is...

Create a button and make it behave like a link. Setting the type attribute to "button" will prevent the button from doing a POST

<button id="cancelButton" type="button">Cancel</button>

Then in your jQuery file,

    $("#cancelButton").click(function () {
        window.location = '../ActionName/' + $("#inputParameterId").val()
    });

I don't particularly care for this solution.  Feels like a hack to me.

Some might want everything to be a link, even though a "Save" button should be a POST.  We could...

Create a link and make it behave like a submit button.

<a id="LinkSave" href="#">Link Save</a>

Then, in your jQuery file,

    $("#LinkSave").click(function () {
        $("#myForm").submit();
    });

AND, to get this to work, your form has to have an ID, so you have to do some extra stuff with your Html.BeginForm helper...

@Using Html.BeginForm("ActionName", "ControllerName", FormMethod.Post, New With {.id = "myForm"})

Besides being ugly and a hack, this only works in IE. So I don't like that either.

Your best bet is to leave POSTing to buttons and GETting to links.  If you apply css in a smart way, you can style them to look the same.  For example:

                        <div class="actionButtons">
                            <input name="Save" type="submit" value="Save" />
                            @Html.ActionLink("Cancel", "ApplicationSummary", New With {.id = Model.Nutshell.ApplicationId})
                        </div>

The CSS looks like this:
.actionButtons A, .actionButtons INPUT {
    font-size: 10pt; 
    color: White; 
    margin: .5em; 
    font-weight: normal;
    text-decoration: none; 
    padding: .15em 1.5em .2em 1.5em;
    background-color: #353535; 
    border: 1px solid black;
}

So, any anchor or input tags inside a container with the "actionButtons" class will have this style.

One final note.  What if you need more than one POST button on the same page?  You could put two submit buttons within the same form and differentiate between the two in the action method using something like:

            If Request("Save") IsNot Nothing Then
                'Save Logic Here
            ElseIf Request("Verify") IsNot Nothing Then
                'Verify Logic Here
            End If

I don't like that because it's hackish and messy. Just put two or more forms on the page, and have each form target a different action method for each submit button.

UPDATE:  OK, so having two forms isn't always practical.  What if you need to submit the same data, but in two different ways depending on what button is clicked?  Go ahead, and put to submit buttons on your form.  Make sure the name attribute is identical. Let's name them both "TheViewButton".  The value attribute will obviously be different.  Your action method will look like this:

<HttpPost>
Function TheViewName(viewModel As TheViewModel, TheViewButton As String) As ActionResult
   If TheViewButton = "Save" Then
      'Save Logic
   Else
      'Other Logic
   End If
End Function

I like this solution a bit better.

Sunday, September 29, 2013

Initial Setup of Android Developer Tools (ADT) and Eclipse

I downloaded ADT from Google which comes with Eclipse.  However, when I tried to run Eclipse for the first time, I got a nasty little error about not finding the JRE.  JRE stands for Java Runtime Environment, and as far as I can tell, it must be the equivalent of the .net framework.  I went into Control Panel and uninstalled anything in there that said Java.  Then I put Java JRE into Google and downloaded Java JRE 7 for Windows 64 bit from an Oracle website.  Once I installed it, I found the files in the Program Files\Java\jre7 folder.  I copied this into the AndroidSDK folder where the eclipse.exe file is.  I then renamed it from jre7 to just jre and voila, it worked.  The nasty error message did say where it was looking for the jre, so thats how I knew where to put the files.

What a start.  Hopefully, everything about android development isn't this weird.

Wednesday, September 25, 2013

Using a jQuery UI widget in on an MVC view

First, you need to add references to the appropriate jQuery libraries. The recommended way to do this is to use NuGet. Right click your project, and click on Manage NuGet Packages. Search online and install jQuery and jQuery UI. This will add the .js files as well as .css files that are used by the widgets. Bundles will be created in your BundleConfig file and these bundles will be rendered in your default layout file. Essentially, rendering a bundle is equivalent to using a <script> tag to reference the .js files. If you use another layout file, you must copy these statements over.

@Scripts.Render("~/bundles/jquery")
@Scripts.Render("~/bundles/jqueryui")

This example will add the functionality of the datepicker widget to a text box. First create a textbox and make sure it has the id attribute:

@Html.TextBoxFor(Function(x) x.ProposedStartDate, New With {.id = "ProposedStartDate"})

I recommend a separate jQuery file for each page that you add jQuery functionality. Create the file, and include a link to this file in your view:

<script type="text/javascript" src="~/Scripts/ViewjQuery/SampleView.js"></script>

In your jQuery files, associate your textbox with the widget by using the following code:

$(document).ready(function () {

    $("#ProposedStartDate").datepicker();

});

Finally, you're not going to like the look of the datepicker, so go to Theme Roller and download a jQuery theme .css file or two. Then reference this css file in the head tag of your layout file thusly:

<link href="~/Content/themes/lightness/jquery-ui-1.10.3.custom.css" rel="stylesheet" type="text/css" />

Finally, you will be satisfied with the look of your datepicker, but you may want to size it down a bit. This has to be done through the font-size css style of a particular class. I don't recommend changing the theme .css that you downloaded. Rather, I would just create a new .css file for these types of tweaks and load it after you load the theme roller css. Put this in there:

.ui-datepicker { font-size:9pt !important}

Monday, September 23, 2013

Use Performance Monitor to monitor memory usage of a web application

Performance Monitor is a tool that is native to all variants of the Windows OS.  Think of it as Task Manager on steroids.  Just do a search for "perfmon", and you'll see it in the start window.

Using Performance Monitor

In the tree view on the left side of the screen click on "Performance Monitor" inside the "Monitoring Tools" folder.  Here you can see real time data collection.  By default it shows processing percentage.  Right click this counter and click "Remove All Counters".  Now, right click and select "Add Counters".  Expand the "Process" category in the list box on the left, and choose "Private Bytes"  Private Bytes is the amount of memory a process has allocated to it exclusively.  In the second list box, select the process that represents the IIS worker process for the web application you are monitoring.  The process is normally named w3wp.  Keep in mind that there is a separate worker process for each application pool.  Application pools can be shared among more that just one web application so you need to dig around in IIS to determine what you are looking for.  If more that one app pool is running, you will see multiple w3wp instances.  You can deduce which worker process is the one you want by comparing the memory usage in peformance monitor with the memory usage in IIS (select the server, then choose worker processes).  I usually just end up selecting them all.  Select "Add" and then "OK".  Now you'll see the memory usage scrolling across the screen.  However, since the usage is in bytes, and the y axis only goes up to 100, the line is just a straight line along the top of the graph.  So, you'll need to scale down the numbers by right clicking each counter, and choosing "Properties".  I have found a scale of 0.0000001 works good for this.

This only shows you data from the last minute or so.  If you want to record usage from a longer period of time, you need to set up a "Data Collector Set".  Expand "Data Collector Sets" in the tree view and right click the "User Defined" folder.  Choose "New" and then "Data Collector Set" from the menu.  Choose a basic template.  Click on your new data collector set, and then double click on Performance Counter.  Remove the counter that's there, and add the counters like you did above.  Then set the sample interval.  Right click the collector set and click properties and select the stop condition tab.  Here you can set how long you want the collector to run.  After setting all of this up, you can right click the collector and choose start.  When it completes there will be a report in the reports folder.

Thursday, September 19, 2013

.net Memory Leak?

It was suggested by a colleague that one of our web applications may have a "memory leak".  An application is said to have a memory leak when it uses memory but doesn't release the memory when it is done with it.  Over time, the server the application is running on will run out of memory.

With .net, (most of the time) you don't need to worry about releasing memory.  Most people don't understand how and when to do it anyway.  You create an object which takes up memory.  The object then goes out of scope and at some indeterminate time in the future, the "garbage collector" process (part of the .net runtime) will clean up and release this memory for you.

The garbage collector will only clean up .net objects.  These are called "managed resources".  Sometimes our .net classes contain references to objects that are not .net.  These are called "unmanaged resources".  .net classes that contain references to unmanaged resources are supposed to implement the IDisposable interface.  This exposes a Dispose method that will free up the unmanaged resource.  You should assume that if you are instantiating an object of a class that implements IDisposable, you should call the Dispose method or declare the object with the Using keyword.  The Using keyword is preferred since it will call the Dispose method even if an exception occurs while using the object.  If you fail to do this, you are taking a risk of the unmanaged resource sticking around in memory forever.  If you create a class that contains an instance of a class that implements IDisposable, then your class should also implement IDisposable and call the Dispose method from your Dispose method.  If you follow these rules, you simply shouldn't have memory leaks.

How do we determine if there is a memory leak?  The only way is to monitor memory usage of the application.  With web applications, this presents challenges.  Web applications can use what appears to be a lot of memory.  However, this does not necessarily indicate a problem.  Especially if the web application is under a heavy load.  The web application will use what it needs as more users make requests.  Web applications run inside a worker process for the application pool that is configured for the web site in IIS.  The process won't give up the memory unless it feels "pressure" to do so by some other process.  Reallocating memory takes processing power, and IIS simply won't do it until it feels it needs to.  As you can see, there are going to be some fluctuations in the amount of memory that an application uses that are not related at all to a problem or a "memory leak".  Another thing to keep in mind is that IIS by default will recycle each app pool approximately once a day.  Recycling the app pool essentially wipes out all the memory and starts fresh.  So, if the app pool is configured to recycle more often than that, you may want to adjust that so you can get a good feel of memory usage over a longer period of time.  So, to determine if there is a memory leak, you cannot rely on memory usage observations in the short term.  You must monitor the memory usage over a long period (a day or two).  If the memory usage gradually increases throughout the period, you probably have a problem.  If the increase is correlated to an increase in load, it may just be normal.

Friday, September 6, 2013

Add an InstallShield LE project for a Windows Service

First you must have a windows service project with a ProjectInstaller class added to it.

Then just add a new project and select the InstallShield Limited Edition Project template.  Walk through the wizard (Project Assistant) and just add the project output from your windows service project.  You do this on the "Application Files" step.  Just click the Add Project Outputs button in the lower right hand corner.  Click the Primary Output check box as shown below:



Then, in Solution Explorer, double-click on "Files" which is under "Specify Application Data".  Right-click your project output, and choose properties.  You'll see this.  Just check that Installer Class checkbox, click OK, and you're good to go.


Visual Studio 2012 and Setup Projects

Out of the box setup and deployment projects no longer exist in Visual Studio with the release of VS 2012.  However, Microsoft officially recommends using a product called InstallShield Limited Edition for Visual Studio which can be downloaded here.  This installs a project template in Visual Studio called InstallShield Limited Edition Project.  There is no official documentation for how to use and configure the product.  You have to rely on other blog posts and a few videos.  From what I can tell, it works great for windows applications.  For a web application, I would not recommend using an installer.  You have to jump through a lot of hoops to configure the installer for this type of application, and it is so much easier to simply have your network admin set up a virtual directory, and copy the files from a location where you have published your files.

Wednesday, August 14, 2013

Lambda Expressions

A function can be sent as a parameter to another sub procedure or function.

For example:

    <Extension>
    Public Iterator Function Filter(aBookEnum As IEnumerable(Of Book), selector As Func(Of Book, Boolean)) As IEnumerable(Of Book)
        For Each thisBook As Book In aBookEnum
            If selector(thisBook) Then
                Yield thisBook
            End If
        Next
    End Function

The selector parameter is defined with the Func type.  This means that a function must be passed in with a return type of boolean and takes a parameter of type Book.

So when we call the Filter extension method, can do the following:

Let's say you have a function that meets the criteria for the parameter:

    Function GetBookOne(myBook As Book) As Boolean
        Return myBook.Title = "Book One"
    End Function

You could send this function as a parameter like this:

Dim MySelector As Func(Of Book, Boolean) = AddressOf GetBookOne
MyBookShelf.Filter(MySelector)

Or you could use a lambda expression and seriously streamline your code like this:

MyBookShelf.Filter(Function(x) x.Title = "Book One")

So, "x" represents the Book input parameter.

Tuesday, August 13, 2013

What is IEnumerable(Of T)?

IEnumerable is the base interface for all generic collections that can be enumerated (iterated through).  Examples of classes that implement IEnumerable include Lists, Arrays, Stacks, and Queues.  You can also write your own classes that implement it.  Any class that implements this interface can have LINQ queries performed on its enumerator.  You can also iterate through the collection using the For Each operator.  T is the type of item that the collection stores.  When you perform LINQ queries, you often get anonymous classes that implement the IEnumerable interface in return.

The System.Linq namespace contains all kinds of extension methods that operate on classes that implement the IEnumerable interface.  This is what allows you to write LINQ queries against these objects.

Use Syntax Highlighter to display code in your Blogger posts

Edit the HTML of your blogger template.  From your blog dashboard, click Template on the left side, and then click the Edit HTML button.  Add the following to the head section.

    <link href='http://alexgorbatchev.com/pub/sh/current/styles/shCore.css' rel='stylesheet' type='text/css'/>
    <link href='http://alexgorbatchev.com/pub/sh/current/styles/shThemeEclipse.css' rel='stylesheet' type='text/css'/>
    <script src='http://alexgorbatchev.com/pub/sh/current/scripts/shCore.js' type='text/javascript'/>
    <script src='http://alexgorbatchev.com/pub/sh/current/scripts/shBrushJScript.js' type='text/javascript'/>
    <script src='http://alexgorbatchev.com/pub/sh/current/scripts/shBrushXml.js' type='text/javascript'/>
    <script src='http://alexgorbatchev.com/pub/sh/current/scripts/shBrushVb.js' type='text/javascript'/>
    <script language='javascript' type='text/javascript'>
    SyntaxHighlighter.config.bloggerMode = true;
    SyntaxHighlighter.all();
    </script>

This example is set up for JavaScript, XML, and VB, but you can find other "brushes" here:

http://alexgorbatchev.com/SyntaxHighlighter/manual/brushes/

Switching to HTML when writing your post, if you wanted to demonstrate a bit of HTML, you do this:

<pre class="brush:xml;">
    &lt;script src="StevesJScript.js" type="text/javascript"&gt;&lt;/script&gt;
</pre>

Note that I had to escape the angle brackets with the &lt; and &gt;.

Symmetric and Asymmetric Encryption (and SSL)

Symmetric encryption requires one shared private key.  This same key is used by Person A to encrypt the message and by Person B to decrypt the message.  They can go back and forth all day long using the same key.  It's great and it's private.  However, the problem is getting the key to the other person.  Physically giving the key to the other person is great, but obviously not practical for an internet situation.

Asymmetric encryption is another technique.  Asymmetric means one-way.  It is another means of encrypting a message, but it can only occur in one direction.  Person A can encrypt a message that only Person B can decrypt.  How?  Mathematics.  You don't really need to understand the cryptography details to understand this.  Person B has a private key.  Mathematically, Person B can derive a public key from this private key.  Due to the miracle of modern math, this "public" key can be used to encrypt a message, but not decrypt the message.  Person B can give this public key out to anyone that he wants to receive a secure message from and only Person B will be able to decrypt the message.  So Person B sends Person A the public key.  Person A encrypts his message using the public key, and sends it to Person B who decrypts the message using the private key.  The big breakthrough here is that a private key never has to be given out.

How are these two methods used?  SSL.  A combination of these two methods is used to establish a secure browsing session.  The web server has a certificate installed that contains the private key.  When average Joe points his browser to the web site, the server will generate a certificate that contains the public key derived from this private key and send it to the browser.  The browser generates something called a "session key" (AKA shared private key ), and sends this to the web server using the public key in the certificate.  Now, the web server and the browser both know the session key (AKA shared private key) and can begin communicating both ways using symmetric encryption.

To summarize, the shared private key is securely given to the web server by using asymmetric encryption.  Once the shared private key is in both party's hands, symmetric encryption can commence.

Tuesday, July 23, 2013

Call a WCF web service using jQuery

First, add an AJAX-enabled WCF Service to your project.  There is a Visual Studio template for this.  Add a web method like the following:

    <OperationContract(), WebGet()>
    Public Function GetFood(inputId As String) As Food()
        Dim ReturnFood As New List(Of Food)
        If inputId = 1 Then
            ReturnFood.Add(New Food With {.Id = "1", .Name = "Bananas", .Color = "Yellow"})
        ElseIf inputId = 2 Then
            ReturnFood.Add(New Food With {.Id = "2", .Name = "Apples", .Color = "Red"})
        Else
            ReturnFood.Add(New Food With {.Id = "1", .Name = "Bananas", .Color = "Yellow"})
            ReturnFood.Add(New Food With {.Id = "2", .Name = "Apples", .Color = "Red"})
        End If
        Return ReturnFood.ToArray
    End Function

Notice the WebGet attribute.  This allows your web method to be called using a GET operation.  Very important.  Won't work without this.  What this means is if you browse to http://yourserver/AjaxGetResultsService.svc/GetFood, you will get Json back in return.

Also notice that I'm returning an array of Food which is a class I made up.  The .net framework will automatically turn this into Json for you.

So, if you had a button with an id of buttonPopulateFood, the following jQuery code would call this method and display the results.

    $("#buttonPopulateFood").click(function () {
        $.ajax({
            url: "AjaxGetResultsService.svc/GetFood",
            type: "GET",
            dataType: "json",
            data: {
                inputId: "1"
            },
            success: function (json) {
                displayJson(json);
            },
            error: function () { alert("You have failed.") }
        });
    });

Here is the displayJson function I'm calling.  I'm using the each function to iterate through the json array.

function displayJson(jsonData) {
    $.each(jsonData.d, function (index, value) {
        $("#food").append(index + ": " + value.Name + ", ");
    });
};

jQuery Basics

JavaScript

JavaScript is a programming language that runs inside a browser.  Because it runs inside a browser, it runs on the user's machine instead of on the web server.  JavaScript code will respond much quicker to events like button clicks than code that runs on the server.  JavaScript also uses a technology known as AJAX to call server code without a time consuming post back.  Incorporating more JavaScript into your web site can speed up and improve the user experience.  However, JavaScript is ugly.  You sometimes have to jump through a lot of hoops to do simple things, including AJAX calls.

jQuery

jQuery is simply a JavaScript library.  It is literally just one file that you download at jquery.com.  It's free and open source (you can't compile JavaScript anyway).  The library contains a bunch of functions that you can call.  The functions do pretty much everything you would want to do with JavaScript, so every line of code you write is just a call to a jQuery function.

To use jQuery, you just need to reference the jQuery library with a line like the following in the head tag of your html page:

    <script type="text/javascript" src="jquery-1.10.2.js"></script>  

You should definitely keep your own JavaScript in a separate file as well:

    <script src="StevesJScript.js" type="text/javascript"></script>

Let's dive into an example to demonstrate how this all works.

Clicking buttons

First, add a text box, a few buttons, and a paragraph to display some results to your page:

   <input type="text" id="textBoxNumber" />  
   <button id="buttonPressMe">Press Me</button>  
   <button id="buttonClear">Clear</button>  
   <p id="results">results</p>

Instead of setting the event attribute on the actual tag, you can associate a click event in your JavaScript file by calling a jQuery function.  This almost feels like a "code-behind" page like you see with ASP WebForms.

$(document).ready(function () {

    $("#buttonPressMe").click(function () {
        $("#results").text($("#textBoxNumber").val())
    });

    $("#buttonClear").click(function () {
        $("#textBoxNumber").val("");
    });

});

The $ function selects an element.  In this case, we select the whole document.  Then we call the ready function for that element.  So this means, after the document loads, whatever is sent to the ready function will execute.  You can see we have selected both buttons by id (using the # symbol) and have called the click function which specifies what to execute when the selected button is clicked.  Here I am simply displaying the contents of the text box and clearing out the text box.

Tuesday, July 9, 2013

"Unable to Start Debugging on the Web Server" error when hosting your web application on your local IIS

It works fine when you host your project using the Visual Studio Development Server, but when you choose IIS, you get this error.  Try the following from a command prompt:

%SystemRoot%\Microsoft.NET\Framework64\{version number goes here}\aspnet_regiis -i

I think this happens when IIS doesn't recognize the version of the .net framework that you are running.  So this might happen when you install a Service Pack for instance.  Anyway, this line of code makes the version known to IIS.  Keep in mind that if you are running version 3.5 that you find this aspnet_regiis executable in the folder for version 2.0.  3.5 shares a common CLR with 2.0.


Enable the Usage Summary page in SharePoint

The Usage Summary page is an administrative page that is useful for monitoring the size of the content database.  Normally,it is available from Site Settings on the parent site of a site collection.  However, if it does not show up, you probably need to enable usage logging by performing the following:


  1. Central Admin
  2. Operations
  3. Under Logging and Reporting, click "Usage analysis processing"
  4. Check "Enable logging" and "Enable usage analysis processing"
  5. OK

LinkButton redirect to a page in a new browser window

Let's say you have a LinkButton control.  If you do a Response.Redirect in the code behind, the page will be opened in the same browser window.  But what if you want the page to open in a new browser window?  Unfortunately, Response.Redirect can't do this.  Javascript on the client or a plain html hyperlink (with target="_blank") is the only way to do this.  The simplest way to do this is to set the OnClientClick code to execute some javascript to make this happen.  Like this:

LinkButton1.OnClientClick = "window.open('http://www.blogger.com', '_blank')"

Then, when the user clicks the button, the javascript will open the link in the new window.  (The server side click event will also fire)

Javascript and ASP.NET

Many ASP.NET server controls provide a property or two for specifying javascript to execute.  For example, a Button control will expose a OnClientClick property where you can specify javascript.  A CustomValidator control exposes a ClientValidationFunction where you can specify a javascript function.

The first thing you need to do is write the javascript function.  The javascript must be enclosed in <script> tags, and can be placed anywhere in the markup.  For example:

<script type="text/javascript">
     function SayHello() {
          alert('Hello');
     }
</script>

Now, you can refer to this function in those properties.  You can set these properties in either the markup or the code-behind.  For example in code-behind, you could write:

Button1.OnClientClick = "SayHello()"

Or, if your javascript is just a one or two liner, you could put the lines of code directly into the property like this:

Button1.OnClientClick = "alert('Hello')"

Sometimes, a server control will not expose a property to execute the script when you want it to.  For example, let's say you want javascript to execute when you change the value of a TextBox control.  A TextBox control will actually render as an html input tag.  The input tag has an attribute of "onchange" which is part of a group of attributes called "intrinsic events".  We can actually stick some javascript in these events with the following code:

TextBox1.Attributes.Add("onchange", "SayHello()")

Now when the TextBox's contents are changed and user tabs off, your script will execute.

One final note.  There is no way to directly call a javascript function from your code behind.  However, by using the above methods, and "injecting" the javascript at run-time, you can effectively accomplish this.


Friday, June 28, 2013

Header Alignment Issue with ASP.NET GridView Control

Without any styling a GridView control's header will display the text in the center of the column.  If you want the header text to be aligned to the left of the column, it can be tricky and not very intuitive to accomplish this.

There are several places (markup not code-behind) in the grid where you can specify a CSS class to apply to the header.  The attribute is called HeaderStyle-CssClass.  This attribute is applicable to the asp:GridView node, or the individual Column nodes (i.e. asp:TemplateField, asp:BoundField, etc.).  There is also a HeaderStyle node which as a CssClass attribute that would mean the same thing.  However, any alignment styling will not work unless the HeaderStyle-CssClass attribute is set on the individual Column nodes.  So, you have to specify the header's CSS Class for each column.  To me this is counter-intuitive, but appears to be the only way to get a header to align a certain way.

Friday, June 7, 2013

SharePoint 2010 will not open PDF files by default

By default, if you click on a PDF file in a document library, the file will not open in a browser.  Instead, a dialog box will show up prompting you to save the document to your hard drive.  This is supposed to "protect" the user from opening up malicious files.  Obviously, if you deal with PDF a lot, you can't expect people to download the file every time they want to edit or just look at it.  It pretty much defeats the entire purpose of the document library.  So, we have to "loosen up" this restriction.  Unfortunately, Microsoft does not provide a way to only "loosen up" this restriction for specific file types.  It's all or nothing.  So, follow these steps:


  1. Central Admin
  2. Manage Web Applications
  3. Select your web application, and click General Settings / General Settings in the Web Applications ribbon.
  4. Select the Permissive setting in the Browser File Handling section.

Tuesday, June 4, 2013

View ALL user profiles in SharePoint 2010

From Central Admin, if you navigate to Manage Service Applications, User Profile Service Application, and then Manage User Profiles, it appears that you can only search for specific profiles using the provided "Find Profiles" box.  However, sometimes you want to see a list of all profiles when looking for something.  Just type the name of the domain in the box, and all profiles tied to an account in that domain will pop up.

Wednesday, May 29, 2013

System.IO.File.WriteAllBytes doesn't work well with large files over a network.

While moving files from one server to another, I would get an "Insufficient System Resources" message when the file was big (around 30 MB).  Turns out, WriteAllBytes works pretty well if you are moving the file around locally, but if you are writing the file to a network share, it can't handle it.  Fortunately, the following code will work:
Using MyStream As New FileStream( _
        FilePath, FileMode.Create, FileAccess.ReadWrite)
    MyStream.Write(Data, 0, Data.Length)
End Using
In this example, I am writing a byte array (represented by "Data") to a file specified by the "FilePath".

Tuesday, May 28, 2013

Internet Explorer 10 breaks debugging with Visual Studio 2010

"Welcome to your new browser!"  Today, automatic updates installed the latest version of IE and I noticed that I got the following error when debugging from Visual Studio 2010:


After some research on the web, it looks like everyone gets this after installing IE 10.  The solution is to register the new IE10 debugger dll.  Apparently, this would happen if you installed Visual Studio after you installed your browser (which is normally what happens).  So use this command as an admin:
regsvr32 "%ProgramFiles%\Internet Explorer\msdbg2.dll"
If you are using a 64 bit box, then use the command prompt here:
C:\Windows\SysWOW64\cmd.exe
Otherwise, just use the standard command prompt.  Remember to run it as administrator.

Add days, months, or years to a date in SQL

Use the following:
DATEADD(month, -3, GETDATE())
This example gets a date 3 months prior to the current date.  Use "day", or "year" in place of "month" to do similar calculations with those units.

Thursday, May 23, 2013

Be mindful of transactions when logging exceptions to a database

The idea behind transactions is this:  When an exception occurs, any database updates defined within the scope of a transaction are not committed to the database.  Either everything works or everything doesn't.  If you are logging exceptions to a database, you have to make sure your logging code is not within the scope of the transaction where the exception is occurring.

This can be tricky when using web services.  I would advise not using the System.EnterpriseServices.TransactionOption web method attribute to implement transactions.  This essentially includes the entire web method within the scope of a transaction.  So, your logging code would also be included in this transaction and would not be committed if an exception occurs.

Replace the attribute with the following code:

Try

    Dim MyOptions As New System.Transactions.TransactionOptions
    Dim MyScopeOption As New System.Transactions.TransactionScopeOption
    MyOptions.IsolationLevel = Transactions.IsolationLevel.ReadCommitted

    Using scope As System.Transactions.TransactionScope = _
      New System.Transactions.TransactionScope(Transactions.TransactionScopeOption.Required, _
      MyOptions)

        ...
        Code goes here
        ...

        scope.Complete()

    End Using

Catch ex As Exception

    ...
    Database logging code goes here
    ...

End Try

Note that when an exception occurs, you leave the scope of the transaction, and are free to commit your logging entries in the database.

Wednesday, May 22, 2013

GacUtil Commands

Use:
gacutil -i "path and name of dll"
to install an assembly in the Global Assembly Cache

Use:
gacutil /u "name of dll without the extension"
to uninstall an assembly in the Global Assembly Cache

GacUtil is a command line utility that comes with Visual Studio.  Just open up the Visual Studio Command Prompt found in the Start Menu.  Make sure you run it as an administrator.

.evt versus .evtx log files

"Classic" .evt log files do not necessarily convert to the new .evtx format.  This becomes an issue when you get sent a log from a Windows Server 2003 server, and need to examine it using the Event Viewer on your Windows 7 pc.  Sometimes you can use Event Viewer's "Save all events as" feature to convert the file to a .evtx file, but this does not always work.  Occasionally you get a "The data is invalid" error.  When this happens, the only way I know of to efficiently examine the log file is to copy it over to a Windows Server 2003 server, and look at it using the old Event Viewer.

Tuesday, May 21, 2013

SharePoint pages are extremely slow to load when debugging

I was debugging a SharePoint project today, and noticed on one of the pages that it took forever to load the page.  It was so slow, you could see the individual controls being painted on the screen.  It only did this while debugging from Visual Studio (2010 in this case).  After some research, I found that turning off IntelliTrace fixed this problem.  This can be done by clicking Debug, Options and Settings, IntelliTrace, and then uncheck the Enable IntelliTrace option.

Friday, May 17, 2013

Delete a sub-site using command prompt

On the SharePoint web server, open a command prompt as administrator.

"C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\14\BIN\stsadm" -o deleteweb -url "url of subsite goes here"

Tuesday, May 7, 2013

SharePoint .net framework version

When writing code that interacts with SharePoint 2010, you have to make sure your project compiles using version 3.5 since this is the version that SharePoint 2010 uses.  By default Visual Studio 2010 will use version 4.0.

"14 Hive" location

C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\14

Property Bag Stuff and SharePoint 2010 Web Services

If you need to access a site property that is stored in the "property bag", you're not going to be able to use any of the SharePoint web services to get at it.  Unfortunately, the only way this is possible is through the object model (specifically SPWeb.Properties).  And of course, this code has to run on the web server.  The advantage of the web services is you can run them anywhere, but as you can see, there are some limitations.

Friday, April 26, 2013

Add a solution to the solution store

To do this, you need to use an stsadm command.  Open a command prompt and run as administrator.  The following line should work:

"C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\14\BIN\stsadm" -o addsolution -filename "path and name of .wsp file go here"

The solution can then be deployed using Central Administration.

Wednesday, April 24, 2013

Add Shortcut to Send To Menu

In Windows 7 or Windows Server 2008 R2, just copy a shortcut here:  %APPDATA%\Microsoft\Windows\SendTo