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.