Friday, January 09, 2009

Adding Bounding Box to Google Maps in ASP.NET

I used this bounding box example code: http://www.svennerberg.com/2008/11/bounding-box-in-google-maps/

And applied it to the ASP.NET control I've already blogged about here - from Jeevan Murkoth on this address - http://dotnet.sys-con.com/node/171162

Basically I added to the GMapControl class:

        private string _sBoundingBox = string.Empty;

 

        /// <summary>

        /// Method to Center and Zoom the map around a bounding box

        /// </summary>

        /// <param name="swPoint">Point at which the map should be South West</param>

        /// <param name="nePoint">Point at which the map should be North East</param>

        public void CenterAndZoomUsingBoundingBox(GPoint swPoint, GPoint nePoint)

        {

            StringBuilder boundingBuilder = new StringBuilder();

            boundingBuilder.AppendFormat("var sw{2}=new GLatLng({0},{1});", swPoint.Longitude, swPoint.Latitude, this.ClientID);

            boundingBuilder.AppendFormat("var ne{2}=new GLatLng({0},{1});", nePoint.Longitude, nePoint.Latitude, this.ClientID);

            boundingBuilder.AppendFormat("var bounds{0}=new GLatLngBounds(sw{0},ne{0});", this.ClientID);

            _sBoundingBox = boundingBuilder.ToString();

            _sZoomAndCenter = string.Empty;

        }


And I modified these GMapControl methods: 

        /// <summary>

        /// Method to Center and Zoom the map at a particular point

        /// </summary>

        /// <param name="curPoint">Point at which the map should be centered</param>

        /// <param name="ZoomLevel">Zoom level</param>

        public void CenterAndZoom(GPoint curPoint, int ZoomLevel)

        {

            _sZoomAndCenter = string.Format("ZoomIn{3}({0},{1},{2});", curPoint.Longitude, curPoint.Latitude, ZoomLevel, this.ClientID);

            _sBoundingBox = string.Empty;

        }

 

        /// <summary>

        /// Method that Generates all the Javascript

        /// </summary>

        /// <returns>Javascript code as a string</returns>

        private string InitializeMap()

        {

            //This is a work around for the thread abort error in IE

            //IE doesn't seem to like script tags in the body so close the form and

            //open another form element

            _sInitFunction.Append("</form>");

            _sInitFunction.Append("<script language='javascript'>\n");

            //Check if the Browser is compatible

            _sInitFunction.Append("if(GBrowserIsCompatible()){\n");

            _sInitFunction.AppendFormat("var {0};", _sGMapVariable);

            _sInitFunction.AppendFormat("var {0}= new Array();", _sArrayVariable);

            _sInitFunction.AppendFormat("{0}\n", myScriptGenerator.GenerateNewOverLayFunction());

            // If pop windows are to be shown then the enable drag has to be set to true

            if (_bOverrideEnabledrag)

                _bEnabledrag = true;

            _sInitFunction.AppendFormat("{0}\n", myScriptGenerator.GenerateGMapVariableInitialization(_sGMapVariable, this.ClientID, _bEnabledrag, _bEnableInfoWindow, _bEnableMapTypeControl));

            _sInitFunction.AppendFormat("{0}\n", myScriptGenerator.GenerateMapType(_MapType, _sGMapVariable));

            _sInitFunction.AppendFormat("{0}\n", myScriptGenerator.GenerateScrollControl(_MapScrollType, _sGMapVariable));

            _sInitFunction.AppendFormat("{0}\n", _sPointOverlay.ToString());

            _sInitFunction.AppendFormat("{0}\n", _sLineOverlay.ToString());

            _sInitFunction.AppendFormat("{0}\n", _sBoundingBox);

            if (_sBoundingBox.Trim().Length > 0)

                _sInitFunction.AppendFormat("{0}.centerAndZoom(bounds{1}.getCenter(),{0}.getBoundsZoomLevel(bounds{1}));", _sGMapVariable, this.ClientID);

            _sInitFunction.AppendFormat("{0}\n", _sZoomAndCenter);

            _sInitFunction.AppendFormat("{0}.addOverlays({1});\n", _sGMapVariable, _sArrayVariable);

            _sInitFunction.Append("}\n");

            //Render the function only if needed.This reduces the  client side  Javascript rendered

            if (_sZoomAndCenter.Trim().Length > 0)

                _sInitFunction.AppendFormat("{0}\n", myScriptGenerator.GenerateZoomInFunction(_sGMapVariable, this.ClientID));

 

            if (_sPointOverlay.Length > 0)

            {

                _sInitFunction.AppendFormat("{0}\n", myScriptGenerator.GenerateOverLayPointFuncCall(_sArrayVariable, this.ClientID));

                _sInitFunction.AppendFormat("{0}\n", myScriptGenerator.GenerateCustomOverLayPointFuncCall(_sArrayVariable, this.ClientID));

            }

            //Render the function only if needed.This reduces the client side Javascript rendered

            if (_sLineOverlay.Length > 0)

                _sInitFunction.AppendFormat("{0}\n", myScriptGenerator.GenerateOverlayLineFuncCall(_sArrayVariable, this.ClientID));

 

            _sInitFunction.Append("</script>\n");

            _sInitFunction.Append("<form>");

            return _sInitFunction.ToString();

        }

 

 And in I modified these JScriptGenerator methods: 

 

            /// <summary>

            /// Method that generates JavaScript code to Initialize the map Variable

            /// </summary>

            /// <param name="sGMapVariable">Variable representing the map</param>

            /// <param name="sClientID">Client ID of the control</param>

            /// <param name="bEnableDrag">Set if the map can be dragged</param>

            /// <param name="bEnableInfoWindow">set if there can be pop up windows on the map</param>

            /// <param name="bEnableMapTypeControl">set if the map Type can be changed</param>

            /// <returns>JavaScript code as string</returns>

            public string GenerateGMapVariableInitialization(string sGMapVariable, string sClientID,bool bEnableDrag,bool bEnableInfoWindow, bool bEnableMapTypeControl)

            {

                  StringBuilder sInitVarBuilder= new StringBuilder();

                  sInitVarBuilder.AppendFormat("{1} =new GMap2(document.getElementById('{0}'));\n",sClientID,sGMapVariable);

                  if(!bEnableDrag)

                  sInitVarBuilder.AppendFormat("{0}.disableDragging() ;\n",sGMapVariable);

                  if(!bEnableInfoWindow)

                  sInitVarBuilder.AppendFormat("{0}.disableInfoWindow() ;\n",sGMapVariable);

                  if( bEnableMapTypeControl)

                  sInitVarBuilder.AppendFormat("{0}.addControl(new GMapTypeControl()) ;\n",sGMapVariable);

                  return sInitVarBuilder.ToString();

            }

 

            /// <summary>

            /// Method to generate the Javascript function to center and Zoom in

            /// at a point on a map

            /// </summary>

            /// <param name="sGMapVariable">Variable representing the map</param>

            /// <param name="sClientID">Client ID of the control</param>

            /// <returns>JavaScript function as a string</returns>

            ///<code>

            /// function ZoomIn(clong,cLat,ZoomLevel)

            ///   {

            ///         map.centerAndZoom(new GPoint(clong,cLat), ZoomLevel);

            ///   }

            /// </code>

            public string GenerateZoomInFunction(string sGMapVariable ,string sClientID)

            {

                  StringBuilder sZoomInFunction = new StringBuilder();

                  //Generate a unique Name for the function

                  sZoomInFunction.AppendFormat("function ZoomIn{0}(clong,cLat,ZoomLevel)",sClientID);

                  sZoomInFunction.Append("\n{");

                  sZoomInFunction.AppendFormat("{0}.setCenter(new GPoint(clong,cLat),ZoomLevel)", sGMapVariable);

                  sZoomInFunction.Append("\n; }");

                  return sZoomInFunction.ToString();

            }


        /// <summary>

        /// Method to Overlay points on the map

        /// Instead of overlaying each point or lay individually

        /// it stores them in an array and overlays them together

        /// </summary>

        /// <returns>JavaScript code as string</returns>

        public string GenerateNewOverLayFunction()

        {

            // The credit for the method goes to Lokkju and is available

            // on the google group  for Google Maps

            StringBuilder sOverLayFunction = new StringBuilder();

            sOverLayFunction.Append("GMap2.prototype.addOverlays=function(a)\n");

            sOverLayFunction.Append("{  var b=this;\n ");

            sOverLayFunction.Append(" for (i=0;i<a.length;i++)\n");

            sOverLayFunction.Append("{\n");

            // SL - changed

            //sOverLayFunction.Append("try{this.overlays.push(a[i]); \n");

            sOverLayFunction.Append("try{this.addOverlay(a[i]); \n");

            sOverLayFunction.Append("a[i].initialize(this);\n");

            sOverLayFunction.Append(" a[i].redraw(true);\n");

            sOverLayFunction.Append(" }catch(er){}\n");

            // SL - changed

            //sOverLayFunction.Append("} this.reOrderOverlays();}; ");

            sOverLayFunction.Append("} }; ");

            return sOverLayFunction.ToString();

        }


This was a lot more involved than I expected - all part of the shift from GMaps version 1 to version 2 and I've no idea what I've broken now....

Thursday, January 08, 2009

Trying to debug javascript in Google Chrome

Using some hints I found on stackoverflow, plus following my own nose a bit, I've tried to get http://www.runsaturday.com working properly under chrome.... but try as hard as I like I can't currently get it working!

There's some sort of web service script comms error which is occurring in chrome but not in firefox 3.

However, the problem is that when I start trying to debug using Chrome's command line debugger then the Chrome browser itself simply hangs :(

I've read about other people saying Chrome's debugger is buggy - but no-one seems to be having as many problems as me - maybe it's my javascript's fault?

For more info on debugging in Chrome, this looks good - http://www.pascarello.com/lessons/browsers/ChromeDebugHelp.html

Configuring DotNetNuke displayname's to be the same as username's

When playing with the DotNetNuke OpenId authentication system, I decided I:
1. Didn't want the OpenId module to set the UserName to the OpenId id
2. Didn't really want separate display and user names any more

Haven't worked out a perfect way to do 1 (haven't worked out how to import an openid profile while still allowing the user to specify their username

But the second one was simple thanks to this post:
http://www.learnmsnet.com/post/Remove-Display-Name-from-Registration-in-DotNetNuke.aspx

So the answer:
- Go to Admin -> User Accounts
- At the bottom of this page choose User Settings
- In the User Settings, set Display Name format to [USERNAME]

That's it :)

Why can I not send mail from my GoGrid Server?

After lots of debugging I eventually found this in the GoGrid KB...

Why can I not send mail from my GoGrid Server?

Outbound e-mail doesn't reach its destination, or is rejected/dropped by default. GoGrid has an access-list at the router which prevents outbound SMTP (a.k.a. the e-mail port). This configuration is intentional so that GoGrid can monitor and effectively combat SPAM (unsolicited e-mail).

In order to have this block removed, you must submit a Support case to GoGrid Support requesting SMTP access. GoGrid Support will reply with a questionnaire which must be filled out and returned.

Wednesday, January 07, 2009

Adding a row number using Linq To Objects

This was a nice little trick for working out a row number in a recordset.

Just use a rowNumber and a post increment :)

                List<LinqToSlodgeRoutes.SlodgeRoutes_Activity> list = linqer.Collect(myUserId);

 

                ListBoxItems.DataTextField = "Text";

                ListBoxItems.DataValueField = "Value";

                int rowNumber = 0;

                ListBoxItems.DataSource = (from x in list

                                          select new

                                          {

                                              Value =  rowNumber++,

                                              Text = string.Format("{2:dd MMM yy} - {2:HH:mm} - {0} - {1} - {3:N2} km", x.Type, x.SubType, x.StartTime, (x.DistanceMetres / 1000.0))

                                          }).Reverse();

 


A look around DNN forum options

So I wanted to install a forum on http://www.runsaturday.com...

The available DotNetNuke options were:
  • The core DNN forum module - currently on version 4.4.3, although there is plenty of talk about a 4.4.4 that went into testing Summer 08 and a 4.4.5 that went into testing Autumn 08. The 4.4.x releases were a huge improvement on the earlier builds and there is heaps of functionality in the core module for free - but still there is lots of talk on the dnn forums about how they could be better...
  • Active Module's ActiveForums - http://www.activemodules.com/Products/ActiveForums/ScreenShots.aspx - a commercially available option (there is a free version, then there are prices $49 upwards) - this module is really well produced and the prices aren't very high... but still too high for me at the moment (and the free one is too restrictive especially without source code).
  • Then I stumbled upon Presstopia's forum - http://presstopia.com/dnn/Default.aspx?tabid=172 - looks really neat and well contained. There are two versions - a free one that looks good - and a source-code included one that you get as part of presstopia's subscription - $20 per month - very tempting....
  • Then I returned to a site I went to a week or two ago - YetAnotherForum - http://www.yetanotherforum.net/ - an open source project which is mainly outside of DNN but which does offer DNN integration. This module has heaps of functionality, comes with full source code and installed first time. It also seems to have very active support - e.g. this guy's avatar collection - http://bunkerhollow.com/files/folders/images/entry560.aspx - and so it's my winner today.... the only downside I could see with it really was that it's integration is a bit "grafted on the outside"  of DNN - but it looks like it's a pretty darned good graft.

Tuesday, January 06, 2009

Making DNN Fly

An interesting post by Mitchell Sellers on how he makes DNN fly (a topic he really is very accomplished on!)

http://www.mitchelsellers.com/blogs/articletype/articleview/articleid/283/how-i-get-my-dotnetnuke-sites-to-run-so-fast.aspx

There's clearly a lot of things to play with and consider - I'll keep looking at this and also will try to measure some things at some point soon.

I've just applied most of his recommendations to runsaturday and it seems quicker... http://www.runsaturday.com/Parkrun/TabId/56/Default.aspx?chartType=3&g0=1&g4=1&evId0=bptt&atId0=2089&evId1=bptt&atId1=537&cpTab=1

However, I can't help but think that the thing that would really make it feel faster still would be me getting the CSS together and removing all the tables (the browser won't render the tables until it knows their sizes - so it has to have downloaded all their innards first!)

Monday, January 05, 2009

Manually inserting empty points into a series in the Microsoft Chart Control - especially looking for gaps of specified lengths.

Been struggling with the manual insertion of empty points into a chart control.

Basically the built in DataManipulation.InsertEmptyPoints method do not search for gaps of a certain length - instead they look for datapoints at positions incremented from the first xValue seen - i.e. if there are data points on 1st Jan, 1st Feb, 1st March, 25th March, 10th April, 1st May. .... then the InsertEmptyPoints method when checking on months would show 1st April as empty - what a fool - sic ;)

Finally worked out how to do what I wanted - but had to use reflector to work it out - the key thing was manually setting the inserted data point to IsEmpty - hope this makes sense.

        

            List<int> emptyPointsPositionsToInsert = new List<int>();

 

            DataPoint previousPoint = series.Points.FirstOrDefault();

            for (int i=1; i<series.Points.Count; i++)

            {

                double numDaysDifference = series.Points[i].XValue - series.Points[i-1].XValue;

                if (numDaysDifference > CurrentOptions.DurationForEmptyPoints)

                {

                    emptyPointsPositionsToInsert.Add(i);

                }

            }

 

            if (emptyPointsPositionsToInsert.Count > 0)

            {

                series["EmptyPointValue"] = "Average";

                series.EmptyPointStyle.BorderDashStyle = ChartDashStyle.Dash;

                series.EmptyPointStyle.BorderWidth = 1;

                series.EmptyPointStyle.BorderColor = Color.FromArgb(200, Color.LightGray);

                if (series.ChartType != SeriesChartType.Area)

                    series.EmptyPointStyle.Color = series.EmptyPointStyle.BorderColor;

                series.EmptyPointStyle.MarkerStyle = MarkerStyle.None;

 

                // reverse the list first (otherwise positions will be all wrong!

                emptyPointsPositionsToInsert.Reverse();

                foreach (int position in emptyPointsPositionsToInsert)

                {

                    double xNewPoint = series.Points[position].XValue - 1;

                    DataPoint newPoint = new DataPoint(xNewPoint, double.NaN);

                    newPoint.IsEmpty = true;

                    series.Points.Insert(position, newPoint);

                }

            }

 


Connecting and reading run data from NikePlus in C#

There's already quite a few posts and examples out there in the blogosphere for how to read data from NikePlus, so I won't explain this in great detail.

But in case anyone is interested, then here's my first stab at some code to do it:

            CookieContainer cookies = new CookieContainer();

 

            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(

                string.Format("https://secure-nikeplus.nike.com/services/profileService?action=login&login={0}&password={1}&locale=en_us",

                "your user name here",

                "your password here"));

            request.CookieContainer = cookies;

 

            using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())

            {

                Stream s = response.GetResponseStream();

                StreamReader reader = new StreamReader(s);

                string text = reader.ReadToEnd();

            }

 

 

            HttpWebRequest requestRunList = (HttpWebRequest)WebRequest.Create(

                "https://secure-nikeplus.nike.com/nikeplus/v1/services/app/run_list.jhtml");

            requestRunList.CookieContainer = cookies;

 

            using (HttpWebResponse responseRunList = (HttpWebResponse)requestRunList.GetResponse())

            {

                Stream s = responseRunList.GetResponseStream();

                StreamReader reader = new StreamReader(s);

                string text = reader.ReadToEnd();

                Debug.WriteLine(text);

            }

 

            HttpWebRequest requestRun = (HttpWebRequest)WebRequest.Create(string.Format(

                "https://secure-nikeplus.nike.com/nikeplus/v1/services/app/get_run.jhtml?id={0}",

                "pick a run from the run list retrieved above"

                ));

            requestRun.CookieContainer = cookies;

 

            using (HttpWebResponse responseRun = (HttpWebResponse)requestRun.GetResponse())

            {

                Stream s = responseRun.GetResponseStream();

                StreamReader reader = new StreamReader(s);

 

                XmlSerializer xmlS = new XmlSerializer(typeof(plusService));               

                plusService plusService = (plusService)xmlS.Deserialize(reader);

 

                Debug.WriteLine("status = " + plusService.status);

                Debug.WriteLine("datatype = " + plusService.sportsData.extendedDataList.extendedData.dataType);

                Debug.WriteLine("intervaltype = " + plusService.sportsData.extendedDataList.extendedData.intervalType);

                Debug.WriteLine("intervalUnit = " + plusService.sportsData.extendedDataList.extendedData.intervalUnit);

                Debug.WriteLine("intervalValue = " + plusService.sportsData.extendedDataList.extendedData.intervalValue);

                string[] items = plusService.sportsData.extendedDataList.extendedData.Value.Split(',');

                foreach (string item in items)

                    Debug.WriteLine("\t" + item);              

            }

        }

 

Where plusService is a class generated using "xsd.exe /classes" on an .xsd file generated from some example xml.

Note: maybe I should explain and expand upon this a bit better - I will when I tidy up the code a bit!

Charting in action

After all the talks of charts in the recent month, I've finally put my http://www.runsaturday.com site live.

Here's an example of some of the charting in action http://www.runsaturday.com/Monthly/tabId/63/subView/Monthly/Default.aspx?StartDate=05%20Dec%202004&UserId=3&UseKm=False

Also embedded here for you to play within inline (in an iframe)

Saturday, January 03, 2009

AWS - S3 - ThreeSharp - Deleting a bucket (must delete it's contents first)

If anyone's interested, then this is the rather crude code I hacked together to delete entire buckets (including their contents) within the ThreeSharp Forms sample for AWS S3
 

        private void button1_Click(object sender, EventArgs e)

        {

            while (listBoxObjects.Items.Count > 0)

            {

                this.listBoxObjects.SelectedIndex = 0;

                using (ObjectDeleteRequest request = new ObjectDeleteRequest(this.comboBoxBucketNames.SelectedItem.ToString(), this.listBoxObjects.SelectedItem.ToString()))

                {

                    //request.RedirectUrl = redirectUrl;

                    using (ObjectDeleteResponse response = service.ObjectDelete(request))

                    { }

                }

                this.listBoxObjects.Items.Remove(this.listBoxObjects.SelectedItem);

            }

 

            using (BucketDeleteRequest r = new BucketDeleteRequest(this.comboBoxBucketNames.Text))

            {

                using (BucketDeleteResponse resp = service.BucketDelete(r))

                {

                    Debug.WriteLine(resp.StatusCode);

                }

            }

        }

DNN5.0 - Can't Upload Images Using Text/HTML (FckHTML) Editor

If you come across this problem then the notes and a workaround (move the FckHTML DLL from bin/providers to bin) are here:
http://support.dotnetnuke.com/issue/ViewIssue.aspx?ID=8716&PROJID=2

Just posting this as it took me a while to find it.


Parser Error
Description: An error occurred during the parsing of a resource required to service this request. Please review the following specific parse error details and modify your source file appropriately.

Parser Error Message: Could not load type 'DotNetNuke.HtmlEditor.FckHtmlEditorProvider.fcklinkgallery'.

DOCTYPE caused AJAXToolkit problems....

It was a late night last night.

I was almost ready to go to bed when I discovered my AJAX Modal Popup Extender was broken in IE!

Basically it was working in every respect except the rather fatal flaw that it was displaying top left of the window and mostly off screen.

This was only occurring in IE and was new behaviour - it used to work....

After lots of swearing, head scratching and searching, I eventually identified that it was not a problem with relative/absolution positioning - there are lots of (out of date?) reports like these around - http://forums.asp.net/p/1076772/1583530.aspx

Instead this problem was caused byt he DOC TYPE declarations that had got added to my project as part of my Facebook Connect and my DotNetNuke 5.0 integration... This link tells a similar story - http://geekswithblogs.net/mnf/archive/2008/09/05/set-div-to-the-vertical-middle-of-the-browser-window.aspx

Basically, to fix this I had to patch and rebuild the Ajax Control toolkit - this is the change I made to the common.js file:

    getClientBounds: function() {

        /// <summary>

        /// Gets the width and height of the browser client window (excluding scrollbars)

        /// </summary>

        /// <returns type="Sys.UI.Bounds">

        /// Browser's client width and height

        /// </returns>

 

        var clientWidth;

        var clientHeight;

        switch (Sys.Browser.agent) {

            case Sys.Browser.InternetExplorer:

                clientWidth = document.documentElement.clientWidth;

                clientHeight = document.documentElement.clientHeight;

                // Workaround - added this code to cope with IE Transitional XHTML

                // - http://geekswithblogs.net/mnf/archive/2008/09/05/set-div-to-the-vertical-middle-of-the-browser-window.aspx

                if (clientHeight == 0 && clientWidth == 0) {

                    clientWidth = document.body.clientWidth;

                    clientHeight = document.body.clientHeight;

                }

                break;

            case Sys.Browser.Safari:

                clientWidth = window.innerWidth;

                clientHeight = window.innerHeight;

                break;

            case Sys.Browser.Opera:

                clientWidth = Math.min(window.innerWidth, document.body.clientWidth);

                clientHeight = Math.min(window.innerHeight, document.body.clientHeight);

                break;

            default:  // Sys.Browser.Firefox, etc.

                clientWidth = Math.min(window.innerWidth, document.documentElement.clientWidth);

                clientHeight = Math.min(window.innerHeight, document.documentElement.clientHeight);

                break;

        }

        return new Sys.UI.Bounds(0, 0, clientWidth, clientHeight);

    },

Slowly moving forwards - DNN5 is alive :)

So I've got DotNetNuke 5.0 up and running on the gogrid server now and it seems to be working OK :)

The big problem which took a long time to resolve was a horrid exception (TargetInvocationException) occurring somewhere in the JSON deserialisation called by the ClientAPI called within the DNN Menu. Really this was disgusting to try to find and it wasn't helped by the fact that I couldn't find the latest WebControls source code anywhere....

Anyways, the solution was a bit disappointing - I had to clear the browser side cookies out - the problem was actually being caused somewhere in the cookie contents! Drats and yuk! I think (hope) these cookies were left over from the previous 4.9 install...

Slowly moving forwards - chart issue of the day

I've just spent some time debugging our server which went to 100% busy.

It turned out to be caused by this line in our code:
        Chart1.Height = new Unit(chartCount * 250.0, UnitType.Pixel);

This went to zero when chartCount was zero... and somewhere in the chart code (presumably somewhere in the layout code?) this zero height caused an infinite loop.

Moral of the story - if you don't want infinite loop busy thread 100% CPU when using Microsoft Chart Control, then don't set the chart height to zero!

Fixed code was:
        Chart1.Height = new Unit(chartCount * 250.0 + 1.0, UnitType.Pixel);

Friday, January 02, 2009

Ongoing DotNetNuke 5.0 Merge Grief...

As part of trying to move this RunSaturday code from 4.9 on my dev box to DNN 5.0 on a GoGrid virtual server.... I've stumbled across all sorts of DNN and ASP issues - on the negative side, this is quite dull... on the plus side, it's all still learning....

So I've carried on and I stumbled across an error "Unknown server tag 'asp:ListView'"

Looking through the ASP.NET forums this seemed to indicate that I hadn't quite correctly ported the DNN web config file correctly to 3.5 from 2.0.... but it looked OK... eventually WinDiff (WinMerge) showed me what was wrong... I was missing this line from the <controls> section of web.config:

        <add tagPrefix="asp" namespace="System.Web.UI" assembly="System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
        <add tagPrefix="asp" namespace="System.Web.UI.WebControls" assembly="System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
        <add tagPrefix="asp" namespace="System.Web.UI.DataVisualization.Charting" assembly="System.Web.DataVisualization, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>

How hard can it be to install SQL Management Studio?

The answer seems to be quite hard....

http://aspadvice.com/blogs/ssmith/archive/2007/09/24/Installing-SQL-2005-Management-Studio.aspx

Even when I followed the advice in this blog and installed the tools separately, then I still was getting any joy in installing the SQL Server Management Studio - basically it kept telling me the "Workstation Components" were already installed.

Eventually I tried:
  • Using the Control Panel add/remove programs tool to remove the shared Workstation Components (being careful to avoid removing SQL Server at the same time!)
  • Then reinstalling using the tools msi package
It worked - but it took way too long to find this uninstall route - I'd rather be coding :)

Thursday, January 01, 2009

Cloud Serving...

OK... so I've started the New Year with a plump for GoGrid...

So I've signed up for a PayAsYouGo server... and I've started using it.

Steps completed so far:

1. I've installed a win2k8 server (easy enough to do)
2. I've added cloud storage (again, easy enough to do)
3. I've connected the win2k8 server to the cloud storage - I did this eventually... but I did misread the instructions (http://wiki.gogrid.com/wiki/index.php/Cloud_Storage:Configuring_Windows_2008_Servers_to_Access_Cloud_Storage) and it did take me an age to work out that I could not FTP direct to the cloud storage - instead I have to FTP or Samba in from one of my servers (not direct from an Internet connected PC)
4. I've set up an FTP server on the win2k8 server and am now uploading to that server. To do this, I had to go to the Windows Server console, then go to the IIS7 settings, add then enable the FTP tools from IIS6 within IIS7... then (and this took some time to work out) I also had to tell the Windows Firewall to let the dynamic FTP traffic through using:

netsh advfirewall set global StatefulFtp enable

So now I'm busy uploading stuff.... more "soon"....