Showing posts with label Visual Studio. Show all posts
Showing posts with label Visual Studio. Show all posts

Tuesday, 14 May 2013

Handling unassigned local variable errors with struct objects in C#

Handling non assigned struct objects in C#

If you have ever used structs and had use of unassigned local variable errors from your editor i.e Visual Studio then there is a simple solution.

The problem comes about because the compiler is not clever enough to realise that the struct object will always be initialised when used.

This is usually because the struct object is initialised within an IF statement or other code branch which makes the compiler believe that a similar situation to the "unreachable code" error has been detected.

As the compile cannot definitely tell that the struct object will always be initialised when it gets used it will raise a compile error.

In Visual Studio it will usually show up with a red line under the code in question with the error message "use of unassigned local variable ..."

Here is a simple example where the struct object is populated with a method and starts off in the main constructor method unassigned.

However because of the nature of the code and the fact that on the first loop iteration oldID will never be the same as currentID (as oldID starts off as 0 and currentID as 1) then the IF statement will always cause the this.FillObject method to run on each iteration.

Therefore the myvar variable which is based on a struct called myStructObj will always get populated with new values from the loop.

However the compiler cannot tell this from the code and will raise the "use of unassigned local variable myvar" error when I try to pass the object as a parameter into the this.OutputObject(myvar) method which just outputs the current property values from the object.
public class Test
{

 /* example of a method that believes the struct object won't get assigned even though due to the if statement it always will */
 public void Test()
 {

  myStructObj myvar;
  int oldID = 0; 

  /* just a basic loop from 1 to 9 */
  for(int currentID = 1; currentID < 10; currentID++)
  {
   /* as the oldID starts as 0 and currentID starts as 1 on the first loop iteration we will always populate the struct object with values */
   if(oldID != currentID)
   {
    /* populate our struct object using our FillObject method */
    myvar = this.FillObject(currentID, "ID: " + currentID.ToString());

    oldID = currentID;
   }

   /* try and parse our struct to a method to output the values - this is where we would get our red line under the myvar parameter being passed into the OutputObject method e.g. "use of unassigned local variable myvar" */
   this.OutputObject(myvar);
  }

 }

 /* Simple method to output the properties of the object to the console */
 private void OutputObject(myStructObj myvar)
 {
  Console.WriteLine(myvar.prop1);
  Console.WriteLine(myvar.prop2);
 }

 /* Simple method to populate the struct object with a string and integer value for both properties*/
 private myStructObj FillObject(string val1, int val2)
 {
  myStructObj myvar = new myStructObj();

  myvar.prop1 = val1;
  myvar.prop2 = val2;

  return myvar;
 }

 /* my struct object definition - using non nullable types */
 public struct myStructObj
 {
  public string prop1;

  public int prop2;
 }
}

Solution to use of unassigned local struct variable

The solution is to either to always initialise the object before you start the loop or to just use the default keyword to ensure your struct object variable is always set-up with default values.

Example Fix

myStructObj myvar = default(myStructObj);

This will get rid of those annoying red lines and use of unassigned local variable errors.

If your struct object is a value type then it calls the default constructor and if it's a reference type you will get a null that you can then test for before using it.

Simples!

Saturday, 9 July 2011

URLEncode Problem with .NET 4.0

Visual Studio 2010 Problem with "The name HttpUtility does not exist in the current context".

I usually use Visual Studio 2010 at work and the Express edition at home. Tonight I was knocking up quick C# windows form application to crawl some specific URL's and I required the ability to URL Encode my URI Components e.g

string url = "http//somesite.com/search?qry=" +  System.Web.HttpUtility.UrlEncode(val);

However even though I had included:

using System.Web;

At the top of my class it was saying that HttpUtility could not be found in System.Web.

This was driving me crazy as I had another project open at the same time which was using the exact same code and it worked.

The advice I found on the web said to ensure that a reference to System.Web was added with the "Project" > "Add References" option.

However when I was searching for this DLL all I could find were System.WebServices and System.ApplicationServices which were obviously no good.

However after a lot of head scratching I went back to the main Project Properties panel and under Target Framework I had ".NET Framework 4 Client Profile" Selected.

I changed this first to .NET Framework 3.5 and then looked again for the reference and it worked!

I added it and then changed it back again to .NET Framework 4. On re-opening the project  all my problems had been solved.

Don't ask me why System.Web doesn't appear as a reference under the Client versions but it doesn't and you need to add a proper DLL reference to get to use this sort of functionality if you are doing non web based apps that require web based functionality like URL or HTML Encode etc.

I thought I would just write a few notes about this in-case anyone else experiences the same problem.

Thursday, 7 April 2011

Moving a C# Windows Service to Windows 7

Problems moving a Windows Service to Windows 7

I have just been given a new PC at work that runs 64bit Windows 7. I have to say so far I quite impressed with the OS and the great thing about Windows 7 is that I can now install IE 9.0 which is blindingly fast and they have finally seen the light and made it standards compliant with support for the DOM 2 event model.

One of the jobs I struggled with today though was making a Windows Service that I had created on my old XP machine in Visual Studio 2010 run on my new box.

The service is basically a BOT that makes SOAP requests behind the scenes to a 3rd party server.

The code was working fine as I had moved it all from a standalone console application that worked but whenever my service harness EXE tried to run I would just get bland _COMPlusExceptionCode errors and nothing of any meaning in the event log.

Debugging a Windows Service was a right pain in the behind and after many uninstalls, installs and lots of shouting I finally got it working.

These steps might not work for everyone but I had to do all of the following to get my service working.

1. Access Rights. Even though I supposedly had administrative rights on my PC I couldn't even install the service with the installUtil [path to exe] command without having to right click on the correct Visual Studio command prompt and choosing "Run as administrator".

However even after doing this I was still having problems starting the service and I was getting the standard

The service did not respond to the start or control request in a timely fashion.

Error message whenever I tried starting the service from the service administrative tool or from my desktop wrapper application.

After some step through debugging I found an "Access Denied" error message was occurring on the ServiceController.Start() method call so I went into the User Account Control Settings and turned the scrolling control right down to "Never Notify". As I wasn't allowed the logon details for the Local System account I was using my own login details for the service as this seemed to be the only way to get round this error message with a reboot.

2. Rebuilding the Service as an x64 solution and not x86. I tried this due to a weird win32 error I was seeing and just put 2 and 2 together and presumed that something was not being run correctly due to it now being on a 64 bit machine.

3. Adding the following code to the config file:

<runtime>
<generatePublisherEvidence enabled="false"/>
</runtime>


I obtained this clue from the following site: stackoverflow.com and it seemed to be the final part of the jigsaw that finally got my service and the wrapper application working on my new machine.

I am fully aware that I am not describing all the reasons behind the decisions I made but I am not exactly aware of the whys and hows at this point in time. However if I come up with further answers I will let you know. Plus if anyone else has any useful links or tips about this issue please add them to the comment section.

Thursday, 10 March 2011

Problems and solutions whilst creating an ASP.NET Web Service

Problems setting up an ASP.NET Web Service

I was recently following a guide to setting up a .NET web service in Visual Studio 2010 and I ran into a few problems.

The guide I was using was Microsoft's own Knowledge Base article which runs through the setting up of a very simple Maths based web service.

Missing Web Service Project Template

The first problem was trying to find the ASP.NET Web Service project template on the start up page of Visual Studio. Step 2 of the guide says:

On the File menu, click New and then click Project. Under Project types click Visual C# Projects, then click ASP.NET Web Service under Templates. Type MathService in the Location text box to change the default name (WebService1) to MathService.
However in Visual Studio 2010 this option was missing. I found out that the reason was due to the default Framework being set to .NET 4.0. The solution is to change the framework to .NET 3.5 and low and behold the Web Service template option was available to select.

I don't know the reasons behind this so don't ask and maybe it's possible to create a web service in .NET 4.0 some other way. If I find out I will update this article.


How to resolve "Could not create type MathServices.service1" error

The second problem I ran into was due to the advice given in step 3 which was to rename the default web service to something else.

Change the name of the default Web service that is created from Service1.asmx to MathService.asmx.
This is fine until you actually build the project and try and access the service on your localhost as it says to do in Step 7.

Browse to the MathService.asmx Web service page to test the Web service. If you set the local computer to host the page, the URL is http://localhost/MathService/MathService.asmx.
When the page loads I was met with an ASP.NET error along the following lines:

Server Error in '/' Application.

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 create type 'MathService.Service1'.

Source Error:


Line 1: <%@ WebService Language="C#" CodeBehind="MathService.asmx.cs" Class="MathService.Service1" >

Source File: /MathService.asmx Line: 1



The reason behind this was that even though I had changed the name of the service I had not changed the code in the .ASMX file to point to the new codebehind. Therefore you need to right click on the .ASMX file in the project explorer and choose the "View Markup" option. Once that is open just change the code to point to the new class like so.

<@ WebService Language="C#" CodeBehind="MathService.asmx.cs" Class="MathService.MathService" %>


Incorrect location for the web service

The knowledge base guide I was following said that the web service would be located on my local machine at the following location:
http://localhost/MathService/MathService.asmx

However when trying this gave me a 404 error. So instead after building the application I clicked the play button which took me to the following location:
http://localhost:1271/MathService.asmx

As you can see this differs due to the port number and missing sub directory. I am pretty sure I haven't missed any steps out along the way and the namespace for my Web Service was setup correctly so I am not sure why this differs from the example.


Creating a Consumer application for the web service

The previous step was important because the next part of the guide was on creating a consumer console application to make use of the web service.

In Visual Studio you select the "Add Service Reference" option from Project menu and then click the "Advanced" button.

On the next page choose the "Add Web Reference" button at the bottom and then on the next page you need to enter the location of your web service in the "URL" box at the top and then hit the little green arrow to the side of it. This will search for the reference at the specified location.

Make sure you know where the web service is located before trying this as the location of my own local web service was not where the knowledge base article said it would be:
http://localhost/MathService/MathService.asmx
instead it was located at
http://localhost:1271/MathService.asmx
Once the web service is found you can add it in the normal manner.

After that change, a re-save and a re-build everything worked fine.

Hopefully this might help others out there who are following the same guide if they run into the same problems.