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}