Archive for the ‘.NET’ Category

Singletracker.net – the technology

Monday, March 18th, 2013

Just a brief post to quickly call out the technologies I’m using in Singletracker.net. In the coming weeks, I’ll try to put up some more posts that get more into the details.

For starters, It’s running in Windows Azure which so far has been really easy to deal with but is going to get too expensive once my 90 day free trial is up.

On the back end it’s Asp.NET MVC 4 with WebAPI and Entity Framework 5. For authentication, I’m using OpenID with Facebook and Google. I plan to add Yahoo and Microsoft soon. If people actually use this, I will probably re-build the back end with node.js, express, and MongoDB.

On the front end, it’s Twitter Bootstrap for the responsive layout and other goodness. I’m using Font Awesome for the icons throughout – I think there is probably not a single image (except the map tiles of course). For the UI, I’m using Backbone.js and Leaflet.js with OpenCycleMap’s tiles.

Introducing Singletracker – crowd-sourced trail conditions for mountain bikers

Sunday, March 17th, 2013

So a few weeks ago I wanted to go mountain biking. I wasn’t sure the trails would be fit to ride on so I went to the websites of the various trails looking for current trail condition info. It was either non-existent or hopelessly out of date.

So I got to thinking, it would be great to have a crowd sourced trail conditions web app. So I built it!

It’s a fairly responsive design – intended to be used on mobile phones (recent versions of iOS and Android) but it should work very well on desktop browsers and tablets. Note that it is intended to be used on modern devices/ browsers – I give ielt9 the Heisman.

V1 is now live. I’m representing the trails as points (think of them as the trail-head) because it’s far easier for a whole bunch of reasons. I’m thinking about ways to handle them as polylines but that’s down the road a ways. I want to get it out there, try to get people using it, get their feedback and see where that takes us.

The zen of it is:

  1. You land at the page and get a map centered on your location.
  2. If there are any trails that have been entered nearby, they will appear as points with different symbols for good, fair, poor, or unknown condition.
  3. You can click/ tap on a point to get a popup containing a bit more information and a button that takes you to the trail details page.
  4. You can also click ‘List’ in the menu to get a list of all the trails in the system sorted by distance from your location.
  5. If you click/tap an item in the list, you go to the trail details page.
  6. On the trail details page there is info about the trail and its condition as well as buttons to: update the trail condition, edit the trail info, or view the trail on the map.

Check it out singletracker.net.

Sending javascript dates to Asp.NET

Friday, July 29th, 2011

I’ve struggled with this at various times and come up with a number of solutions, none of which were entirely satisfying. Now, thanks to Stackoverflow, I found a really nice solution:

Javascript:

obj.date = new Date().toUTCString();

C#:

DateTime date= DateTime.ParseExact(obj.date,
                                  "ddd, MMM d yyyy HH:mm:ss GMT",
                                  CultureInfo.InvariantCulture);

Mobile Device Detection and Android

Tuesday, March 15th, 2011

We’ve been doing more and more apps for mobile devices. Specifically we’ve built some apps recently that we want to work from desktop browsers, tablets, and smartphones.

I’ve heard the argument that you should just serve good semantic html and style it appropriately for the device and be done with it. But we’re not building content driven websites, we’re building data driven web apps often containing maps. We need to give the user an entirely different experience on a phone vs a desktop browser.

We’re using a custom mobile view engine in ASP.NET MVC (based on the one in this Scott Hanselman post) to serve the appropriate view for the requesting device. That’s been working great but one problem I’ve run into is how to distinguish an Android tablet from an Android phone. I finally found the solution to this problem on the Android Developers Blog. Basically, if a device runs android, it should contain the string “android” in the User-Agent string. Google recommends that “manufactures of large-form-factor devices (where the user may prefer the standard web site over a mobile optimized version) remove ‘Mobile’ from the User Agent”. That would be great except that Motorola has already screwed this up by including “Mobile” in the User-Agent of the Xoom.

The Request.Browser object in ASP.NET has a bunch of properties that tell you about the requesting device. But it’s not really sufficient (and some of it is just plain wrong or absent) for accurately identifying the capabilities of mobile devices. So we’ve started using 51degrees.mobi. It uses the WURFL database, which seems to be the most complete and up to date database of mobile devices, to populate tons of useful info on the Request.Browser object. One thing I didn’t realize at first is that besides accurately populating the existing properties of the Request.Browser object, it also makes available many of the other properties exposed by WURFL. They can be accessed like so: Request.Browser["is_tablet"]. We’re now using that in conjunction with the custom mobile view engine.

There are two drawbacks to the 51degrees.mobi component: It adds some overhead to every request. I haven’t really seen a lag but it’s gotta cost something. The more significant drawback is that you have to manually update the WURFL XML file.

Update: I don’t know if I was mistaken about the Xoom’s User-Agent or if Motorola has fixed it in a later revision but I now own a Xoom and the User-Agent does not contain “mobile” (which is correct, it should not). Also, the 51Degrees.mobi component is now available via NuGet, which, if you use Visual Studio, you should be using.

Google Maps Extender for the JS API and SSL

Friday, April 9th, 2010

I recently needed to enable SSL on an ArcGIS Server map service that I was consuming with the Google Maps Extender for the Javascript API. This was not as straightforward as I expected so I thought I’d post about some of the pitfalls that I ran into. Note that I did this on the ArcGIS Server 10 pre-release but previous versions should be similar. I’ll do this in the form of a checklist and I’m just gonna hit the high points. Lots more information can be found at the links provided or you can post a comment and I can elaborate:

  1. Before you do anything, change the ‘Clear Cache Options’ for ArcGIS Server to periodic and set the interval to something very short like 1 minute. That way you won’t have to remember to clear the cache every time you make a change. Don’t forget to change this setting to something more reasonable when you’re all done.
  2. For this project I was planning to implement token based security too and was just gonna take it one step at a time so I would know why stuff broke when it inevitable did. So the first step was to implement ESRI’s proxy page. The instructions here are very good.
  3. Then you’ll want to configure the Google Maps Extender to use the proxy. You do that with javascript like this:
        esri.arcgis.gmaps.Config.proxyUrl = 'proxy.ashx';
        esri.arcgis.gmaps.Config.alwaysUseProxy = true;
  4. Here’s where I ran into my first problem. My dynamic map service layer wasn’t coming through. I fired up Firebug and saw the problem: esri.arcgis.gmaps.DynamicMapServiceLayer do an export map request then they do a ‘Get’ for the map image using the url returned from the export map request. The url for the map image pointed to the arcgisoutput directory which was not configured in my proxy. There are a couple of ways you could fix this problem but I hit it with a hammer: I just configured the proxy to proxy all requests to that hostname. And it worked!
  5. Get an SSL certificate for your ArcGIS Server. ESRI’s instructions here were helpful. I used a self signed certificate since this is for development/ testing.
  6. Next you need to setup your map service to require ssl. You do this in ArcCatalog at the folder level. So open ArcCatalog, connect to the server, right click on the folder that contains your map service, select ‘Properties’, check the ‘Require Encrypted Access’ box, and click ‘OK’.
  7. Now you can change the url’s in your proxy config and your javascript to point to the https url.
  8. Here’s where I ran into problems. The webserver where the proxy was running was not accepting the certificate of the ArcGIS Server. I know what to do, I thought, so I tried to hit the page in IE from the webserver and, as expected, got a message saying the certificate wasn’t trusted. So I went to the page anyway then viewed the certificate. Then I installed the certificate. But when I ran the app again, the certificate was still refused. Finally, I found this post which pointed out that I had just installed the certificate for the logged on user. Follow the link for instructions on how to install it for the local machine.
  9. But then it still didn’t work. So I fired up Firebug and saw what was happening: Remember above where I talked about how Dynamic Map Service Layers work? Well what was happening now was that the output directory url that was being returned by the export map request wasn’t an ssl url so since my proxy was only configured with the https url, it wouldn’t proxy the map image requests. I didn’t find any documentation on this (I didn’t look very hard) but I fixed it by adding another output directory just for ssl and configuring my map service to use it. You do this in ArcCatalog: Right click on your connection to the ArcGIS Server, click ‘Server Properties’, and go to the ‘Directories’ tab. Select ‘Output Directory’ from the ‘Directory Type’ list and then click add. Now give it the path to the directory you want to use (I created an arcgisoutputssl directory right next to the arcgisoutput one) and give it a virtual directory(I used https://<hostname>/arcgisoutputssl) and click ‘OK’ and ‘OK’.
  10. Now at this point you might be thinking that you’re done as I was. But it still didn’t work. I was getting 404′s from the map image requests. I assumed since the AGS post install creates those virtual directories that when I added an output directory it would create its virtual directory for me. But it doesn’t, so go ahead and create your virtual directory and don’t forget to set it to require ssl.

That’s it! Hope this helps somebody.

HtmlHelper methods and dijit widgets

Wednesday, August 5th, 2009

This is certainly not earth-shattering but it’s pretty cool. Asp.Net MVC HtmlHelper methods return a string of html and are used to render html elements. They are cool because you can use them to change the way the control is rendered at runtime based on what you’ve got in ViewData or your model. What’s even cooler is that you can pass html attributes (including custom ones like dojoType) to the HtmlAttributes parameter. This allows you to use HtmlHelper methods to render dijit widgets like so:

<%=Html.TextBox("search_StreetAddress",
  Model.Criteria.StreetAddress,
  new { dojoType = "dijit.form.TextBox", trim = "true" })%>

<%= Html.DropDownList("CityId", Model.CitySelectList,
  new { dojoType = "dijit.form.FilteringSelect" })%>

<%= Html.TextBox("Year", Model.Year,
  new { dojoType = "dijit.form.NumberTextBox",
  constraints = "{min:1900, max:2500, pattern:'0000'}",
  required = "true",
  rangeMessage = "A 4 digit year is required",
  invalidMessage = "A 4 digit year is required" })%>

Using dijit.form.DateTextBox with Asp.Net

Wednesday, August 5th, 2009

Since there’s no date literal in javascript, there’s no standard way of serializing/ deserializing dates. MS Ajax uses \/Date(<ticks>)\/ where ticks is the number of milliseconds since midnight 01/01/1970. It’s a reasonable approach – unambiguous and easy to transform in both directions. For a while I was transforming this date object into a date before sticking it into a dojo DateTextBox, and transforming it back before sending it up to the server. But then I got smart and extended dijit.form.DateTextBox to handle this itself. Here’s the code:

dojo.provide('mjuniper.widgets.DateTextBox');
dojo.require('dijit.form.DateTextBox');

/*A dojo datetextbox that handles sending dates
to and recieving dates from asp.net*/
dojo.declare('mjuniper.widgets.DateTextBox',
  dijit.form.DateTextBox,
  {
      // prevent parser from trying to convert to Date object
      value: "",

      postMixInProperties: function()
      {
        this.inherited(arguments);

      //if it's null, return
      if (!this.value)
      {
        return;
      }

      if (this.value.indexOf('/Date(') > -1)
      {
        //extract the ticks from the json object
        var ticks =
          this.value.substring(this.value.indexOf('(') + 1);
        var endChar = (ticks.indexOf('-') === -1) ? ')' : '-';
        ticks = ticks.substring(0, ticks.indexOf(endChar));
        //instantiate a date
        this.value = new Date(parseInt(ticks));
        //if it's invalid, set value to null
        if (this.value == 'Invalid Date') { this.value = null; }
      }
    },

    /*override the serialize method to write
    back to the server in proper format*/
    serialize: function(dateObject, options)
   {
      return '\/Date(' + dateObject.getTime() + ')\/';
    },

    /*override setValue so we can set it with the
    json date object we get from .net*/
    setValue: function(dateString)
    {
      if (dateString.indexOf('/Date(') > -1)
    {
    //extract the ticks from the json object
    var ticks =
      dateString.substring(dateString.indexOf('(') + 1);
    var endChar = (ticks.indexOf('-') === -1) ? ')' : '-';
    ticks = ticks.substring(0, ticks.indexOf(endChar));

    arguments[0] = new Date(parseInt(ticks))
    this.inherited(arguments);
    }
  }
});

There are obviously a number of ways I could have handled extracting the ticks from the json string (including a regex, but then I would have had two problems). This one is not very elegant but it’s relatively easy to understand and I was able to get it working quickly.

dojo.query – putting it all together

Wednesday, August 5th, 2009

So I guess this will be the finale to my series of posts on dojo.query. I’m using dojo.query to validate data entered into dojo dialogs. In this post, I discussed getting dialog content from an Asp.Net MVC controller method. In the onDownloadEnd function, I do any setup of the dialog that is necessary including something like this:

var onValueChanged =
        dojo.hitch(this, this.dialogValueChanged, dialogId);
//gotta be keyup -
        //validation is out of sync if you use keydown or keypress
dojo.query('input[type="text"], textarea', dialogId)
        .connect('onkeyup', onValueChanged);
dojo.query('select', dialogId)
        .connect('onchange', onValueChanged);
dojo.query('.dijit', dialogId).widgets()
        .connect('onChange', onValueChanged);

This query’s for input elements in the dialog and connects each element’s appropriate method to the function where I do the validation (dialogValueChanged). Note the use of the widgets method discussed in this post.

Here’s the validation function:

dialogValueChanged: function(dialogId)
{
  //check if everything is valid
  var valid = dojo.query('[widgetid], [widgetId]', dialogId)
    .widgets().every(function(widget)
    {
      if (widget.isValid)
      {
        return widget.isValid();
      }
      //if it is not a widget
      //or does not have an isValid method, return true
      return true;
    });                                

    //enable/ disable the save button based on whether it's valid
    var action = (valid) ? 'removeAttr' : 'attr';
    dojo.query('.dialogSaveBtn', dialogId)
	  [action]('disabled', 'disabled');
}

Here we’re querying for widgets and using our previously discussed widgets method to get the actual widgets (not just the dom nodes). Then we use the every method of NodeList to call the isValid method on each widget. The every method will return false if any of the widgets’ isValid methods returned false. Then we use the value returned from every to set our ‘action’ variable and use query again to enable or disable our save button(s) by adding or removing the disabled attribute. Note the use of the removeAttr method we added to NodeList in this post. Note also that this all depends on all the input elements on the dialog being dijit widgets. This mechanism can be easily extended to handle non-dijit elements too.

Re-throwing exceptions in .Net

Thursday, March 19th, 2009

I knew that I read somewhere that there was a very important difference between throw; and throw ex; when you catch an exception and want to re throw it. But I couldn’t remember what the difference was. Thanks to this post I now know. If you use throw ex, the stack trace info will be overriden. So it is almost always preferable to use just throw.