The importance of name giving

by Mikael Henriksson 31. January 2009 14:49

Don’t remember who wrote it but I experienced it first hand tonight. I got it from Clean Code or some other great book I read. I can’t remember the exact frase but it goes something like this –“You give the name of your methods the same thought process as you would a child”. Something like that. For me it was not the name of a method but rather a user control. You see I have just started working with MVC (love it by the way) and I was trying to do a simple

<% Html.RenderPartial("Login"); %>
This worked very well until I tried to visit the actual ActionResult View. For some reason I got a StackOverFlowException and while debugging it it looked like Html.RenderPartial is taking the name of the ActionResult and get stuck in an infinite loop. A simple renaming the user control Login to LoginControl and do the following solved my problems:
<% Html.RenderPartial("LoginControl"); %>
It is an extremely silly problem really but it still got me thinking that name giving is one of the most important aspects of programming!

Tags:

MVC

Html.DropDownList Not Working?

by Mikael Henriksson 31. January 2009 14:17

It’s actually pretty though not very easy to grasp and I couldn’t really find any information about my little problem but here is my explanation on how to get it working! :)

All you need to do is:

<%= Html.DropDownList("CustomerID") %>

And this is why. I know it says that the DropDownList takes a SelectList as a second parameter but you actually supposed to solve this issue in the controller (And this is a very good solution since it makes the presentation layer way less cluttered (logic should NOT be in the Views)!

public ActionResult Edit(int id)
{
    var invoiceRepository = new InvoiceRepository(1);
    var invoice = invoiceRepository.GetSingle(id);

    IList<Product> products = invoiceRepository.GetProducts(id);
    IList<Workday> workdays = invoiceRepository.GetWorkdays(id);

    invoice.CompanyReference.Load();
    int companyId = invoice.Company.ID;
    ICriterion<Customer> criterion = 
		new Criterion<Customer>(c => c.Company.ID == companyId);
    var repository = new Repository();
    IList<Customer> customers = repository.GetAll(criterion);
    ViewData["Products"] = products;
    ViewData["Workdays"] = workdays;

    ViewData["CustomerID"] = new SelectList(customers, "ID", "Name");
    ViewData["Invoice"] = invoice;

    return View(invoice);
}

What I do here is to tell the the presentation layer that the CustomerID contains a SelectList of Customer and that the value field is ID and the display field is Name. Then MVC handles this for you!

Tags:

MVC

Getting started with MVC

by Mikael Henriksson 28. January 2009 23:19

There has been ALOT of improvement in the new version of MVC. I have just gotten started but so far I love it. It is expressive and feels much more intuitive that regular asp.net. You can pretty much extend the existing functionally as much as you like and only the sky is the limit. Wait, stars is the limit.. no there is no limit!

The new feature with sending a file straight to the browser is great. Basically you just create a “dummy” holder class (if you want) for file information like:

   1: public class Image
   2: {    
   3:     public int ImageId { get; set; }    
   4:     public string FileName { get; set; }    
   5:     public byte[] Content { get; set; }    
   6:     public string Mime { get; set; }
   7: }

Now you can easily choose how to send this to the browser. Question is what do you want to do with the file? You can force download or let the browser render it.

To download a file (image, pdf etc.) do the following

   1: public ActionResult DownloadImage(int id)
   2: {
   3:     ICriterion<Image> criterion = new Criterion<Image>(i => i.ID == id);
   4:     Repository repository = new Repository();
   5:     var image = repository.GetSingle(criterion);
   6:     return File(image.Content, image.MimeType, image.FileName);
   7: }

 

The only thing you have to do differently to render the image in the browser instead is to leave the file name out of the return statement. The third parameter just tells MVC to send the file as an attachment. The code to display the image:

   1: public ActionResult DisplayImage(int id)
   2: {
   3:     ICriterion<Image> criterion = new Criterion<Image>(i => i.ID == id);
   4:     Repository repository = new Repository();
   5:     var image = repository.GetSingle(criterion);
   6:     return File(image.Content, image.MimeType);
   7: }
 
The next thing I learned today and this is something I think everyone needs to learn is how to successfully render and display data from different views. Let’s take an invoice as example. The rows (invoice lines) belongs to the aggregate root Invoice and should not be accessible anywhere else. There for I wont create a view for invoice lines. But how do I display the invoice lines when I view the Invoice Details?
It’s real easy, kudos to everyone at the MVC team for making it so easy :) Create a UserControl like InvoiceLinesUserControl (Have a problem with long descriptive names? Read this blog post).

Since the release candidate of MVC the code behind of the view pages is gone. To tell the view what type of data is expected we now do that with Inherits:

   1: <%@ Page Title="" Language="C#" 
   2:     MasterPageFile="~/Views/Shared/Site.Master" 
   3:     Inherits="System.Web.Mvc.ViewPage<Core.Invoice>" %>

Then we need an action result to get some useful data to display in the view Invoice.Details.

   1: public ActionResult Details(long id)
   2: {
   3:     var invoiceRepository = new InvoiceRepository(companyId);
   4:     var invoice = invoiceRepository.GetSingle(id);
   5:     ViewData["Message"] = "Details for invoice : #" + invoice.InvoiceNumber;
   6:  
   7:     IList<InvoiceLines> invoiceLines = invoiceRepository.GetInvoiceLines(id);
   8:     ViewData["InvoiceLines"] = invoiceLines;
   9:     return View(invoice);
  10: }
From here on out it’s a walk in the park. To display the invoice details data I can just do 
   1: <%= Html.Encode(Model.InvoiceTotal) %>

and to render the user control with the quantity and unit price I just Render Partial and tell that method which view data to use like this:

   1: <% Html.RenderPartial("InvoiceLinesUserControl", ViewData["InvoiceLines"]); %>

Tags:

MVC

How do I log from asp.net to Event Log?

by Mikael Henriksson 27. January 2009 19:00

This has been bugging me for quite some time with throwing exceptions when I try to log from an asp.net page to Event Log. The solution is quite simple but it eludes me why nothing has been written about. At least not anywhere I have looked.

  1. Go to run (win+r) type in regedt32.
  2. Navigate to HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\EventLog
  3. Right click, select permissions and Add the ASPNET account (IUSR as well????) with full rights
  4. Make sure that all child objects get the same rights

Done, now you can start logging to the event log.

Tags:

Windows Server

Making good use of the Entity Framework in a Windows Forms application…

by Mikael Henriksson 27. January 2009 18:59

I have been abusing the Entity Framework lately so I thought I’d share some of what I have learned. First of all I must say there are quite a few things that need improvement. It is good that you can generate a model straight from the database and work towards your generated classes BUT! That’s about all you can do real easy… I could not find an easy enough way to customize these generated classes so I still have to use some “object datasources” if you will.

The most straight forward way to use the Entity Framework in a Windows Forms application is to create sort of a proxy class for the entity objects. Let’s say you have a generated class called Person. Create a class called PersonProxy.cs. In this “proxy” class you keep all business logic. The class should look something like:

namespace YourNamespace 
{ 
    using YourModelNamespace; 
    public class PersonProxy 
    { 
        private YourEntityContext context; 
        public PersonProxy() 
        { 
            context = new YourEntityContext(); 
        }

        public IList<Person> GetPersons() 
        { 
            var query = from p in Person 
                        select p; 
            return query.ToList(); 
        }

        public void CreatePerson(string firstName, string lastName) 
        { 
            Person p = new Person() { FirstName = firstName, LastName = lastName }; 
            context.AddObject("Person", p); 
            context.SaveChanges(); 
        } 
    } 
}

And instead of having the entity context straight in your form1.cs you can separate the business logic from the data logic a bit more than I used to do. Now in your form1.cs or whatever your form is called you instead use the proxy class. For several reasons obviously but my main point here is readability and to cut down the lines of code in the code behind of your form.

The form class would the end up in line with:

namespace WinClient 
{ 
	public partial class Form1 : Form 
	{ 
		private PersonProxy proxy; 
		public Form1() 
		{ 
			InitializeComponent(); 
		} 
		private void Form1_Load(object sender, EventArgs e) 
		{ 
			proxy = new PersonProxy(); 
			dataGridView1.DataSource = proxy.GetPersons(); 
		} 
		private void button1_Click(object sender, EventArgs e) 
		{ 
			proxy.CreatePerson(txtFirsName.Text, txtLastName.txt); 
		} 
	} 
}

You still have an open connection to your entity model, remember that the proxy class took care of this? Any validation against your model is done in realtime so hooking up some validation events of a datagridview should be a walk in the park. You also wont have to watch all those “AddObject”, EntityKey etc. That is visible to the proxy-class where we want it. The proxy class should also handle any kind of logic that is bound to the entity model. If you need to find what the next order number is or if an email is already taken that should be done in the proxy.

I hope this proves useful to anyone working with the Entity Framework. As I wrote earlier, it still feels “restricted” in ways. It is hard to create a complete domain model with the help of entity framework. I still have to take shortcuts but for me it is definitely worth it.

Tags: ,

Entity Framework | Windows Forms

How do I configure Windows 2003 Server for Remote Applications?

by Mikael Henriksson 27. January 2009 18:59

My first try at this was to just let the user run a program set from "environement" under Users & Computers. It works ok, but the users where not satisfied with having to relogin if my application crashed. Second try was today and it's not completely finished but I'm getting there. Since the users are logging on to the server from thin clients I dont want them to be able to change anything on the server. Thats why I only allowed a program to be run in the remote desktop session. As soon as the application ended the remote desktop session ended.

Now this is how you do it!

  1. Download and install FC81887&displaylang=en" title="Group Policy Management Console">Group Policy Management Console
  2. Create a new security group in "Users & Computers"
  3. Open up gpmc.mmc and create a new policy, preferably named like the the security group so that I may easily be able to distinguish it.
  4. Add the newly created security group to the policy and make sure the group has read and apply rights to the policy.
  5. Remove most things from Start Menu, Windows Explorer and desktop. I might also like now want to remove access to control panel and task manager.
  6. Make sure that I hide the system drive (C:\) and have the users run their applications from let's say the D: drive with full access to a particular folder.
  7. Create a .vbs script to launch the application
  8. Place a shortcut to the application should it crash
  9. Do a policy update "cmd.exe gpupdate /force"

I found a great article to help me out. I did need to change a few things in the script though this is what my script looks like.

 

 

On Error Resume Next
Set fs = CreateObject ("Scripting.FileSystemObject")
Set WshShell = WScript.CreateObject ("WScript.Shell")

'Get the username and profile directory
MUser = WshShell.ExpandEnvironmentStrings ("%USERNAME%")
MUserProfile = wshShell.ExpandEnvironmentStrings("%USERPROFILE%")

'Delete icons
fs.DeleteFolder MUserProfile & "\Start Menu\Programs\Accessories",True
fs.DeleteFile  MUserProfile & "\Start Menu\Programs\*.lnk"

'Run the app

wshShell.Run "D:\Company\bin\%USERNAME%\Application\app.exe"

' Connect to wmi
set objWMIService = GetObject("winmgmts:root\cimv2")
Do
  found = false
' List the processes
strQuery = "Select * from win32_process where name='app.exe'"
set colProcesses = objWMIService.ExecQuery(strQuery)

for each proc in colProcesses

   ' Get the reference class linking processes to sessions to get the session object path
   strQuery = "References of {win32_process.handle='" & proc.handle & "'} where ResultClass=Win32_SessionProcess"
   set colSessionReferences = objWMIService.ExecQuery(strQuery)

   for each oSessionReference in colSessionReferences
      'Get associators of the session object that are user accounts (linked by win32_loggedonuser)
      strQuery = "Associators of {" & oSessionReference.antecedent & "} where AssocClass=win32_LoggedOnUser"
      set colUsers = objWMIService.ExecQuery(strQuery,,48)
        for each user in colUsers
         if user.name = MUser then found = true
      next
   next
next
Loop While found = true

'Run the Windows 2003 logoff utility
wshShell.Run "c:\windows\system32\logoff.exe"

Sweet! All done! Thanks a bunch to Amit Zinman

 

Tags:

Windows Server

Handle enums gracefully...

by Mikael Henriksson 27. January 2009 18:59

As of lately I have been trying to use Enums wherever I can. In the project I just finished I had a bunch of buggy code and wanted more detailed descriptions so I began writing a grand class to handle all the exceptions. I decided to use and Enum for describing all the different logging routines but when I needed to actually do something based on more than one LogType I ran in to patrol. I wanted to iterate through the declared enum type for the class and log to all types in a sweep. First I got kind of confused looking at my code and since I wanted the others in the team to be able to use it easily I had to rethink. First thing was to refactor the class to something really simple, then begin adding my "normalized" methods but I got stuck at not being able to gracefully looping through my enum.

Let's say I have an enum like this:

[Flags()]   
public enum LogType   
{
	/// <summary>Exception will be logged to a text file</summary>  
	TextFile = 1,
	/// <summary>Exception will be logged to the application event log</summary>
	EventLog = 2,
	/// <summary>Exception will be logged via email</summary>
	Email = 4,
	/// <summary>Log to a website</summary>
	WebSite = 8,
	/// <summary>Log to a database of your choice</summary>
	Database = 16,
	/// <summary>A summary of all LogSources</summary
	All = TextFile | EventLog | Email | WebSite
}

The above code should be a no-brainer, if you don't understand it you should probably buy a book! :)

I found a great tool for making my work extremely readable for my college by the way, it's called Ghost Doc and if you have not tried it yet I urge you to! The project can be found over at http://www.roland-weigelt.de/ghostdoc/
If you are stronger in the code than my granny was I believe you should have no problems reading the following code either, and making good use of it!

public static Collection<T> ConvertEnumValuesToCollection<T>(T enumInputValue) 
where T : struct { Type enumType = typeof(T); if (!enumType.IsEnum) { throw new ArgumentException(enumType.ToString()
+ " Is not an Enum.", "T", null); } Array enumValues = Enum.GetValues(enumType); long inputValueLong = Convert.ToInt64(enumInputValue); Collection<T> enumOutputCollection = new Collection<T>(); foreach (T enumValue in enumValues) { long enumValueLong = Convert.ToInt64(enumValue); if ((enumValueLong&inputValueLong)==enumValueLong&&enumValueLong!=0) { enumOutputCollection.Add(enumValue); } } if (enumOutputCollection.Count == 0 && enumValues.GetLength(0) > 1) { T enumNoneValue = (T)enumValues.GetValue(0); if (Convert.ToInt64(enumNoneValue) == 0) { enumOutputCollection.Add(enumNoneValue); } } return enumOutputCollection; }

No credits at all to me for this one though, I stumbled upon it by mistake but since having computer crashes etc I cannot give my credits to the right webby unfortunately. Hugs and kisses for this though and definately worth sharing. If you have any questions what so ever about enums, flags or .net the myth the legend and the framework I recommend contacting Krzystof Cwalina. One of the chief architects over at Microsoft. If you just want to learn some more about enums I recommend you checking his extremely extensive do's and don'ts out over at http://blogs.msdn.com/kcwalina/archive/2004/05/18/134208.aspx

Tags:

C#

Increase performance of a databound DataGridView

by Mikael Henriksson 27. January 2009 18:59

This was a hard nut to crack. I was just about to pull out my railgun and frag that stupid control for good. Though as soon as I got my hands on the railgun I got tele-fragged by the creators. After 2 days of searching on the internet I actually found something useful on MSDN. Over at http://msdn.microsoft.com/en-us/library/ha5xt0d9.aspx they say that databound grids can be slow in a few scenarios. The one that effected me though was that I had Autosize on both rows and columns. When I set AutosizeColumns = AllHeaders and AutosizeRows = None the problems were gone.

It got me thinking though, all things like resizing enabled should affect performance. I won’t think more on it. I am happy to have gone from 5-10 seconds loading 80 rows to 300 milliseconds loading 11000 rows. :)

Tags:

Windows Forms

How do I install Bluetooth in Windows 2008 Server x64?

by Mikael Henriksson 27. January 2009 18:59

I had problems with this and the reason is obvious. You should not use any type of wireless on a server operating system. I do however like many other use Windows 2008 Server x64 on my laptop for development and work. It is far superior to Vista x64. You get all these goodies that is not available from scratch in Vista, like Hyper-V, domain management tools etc.

One of the main reasons I use a laptop is to get rid of as much wires and cables as is possible. That's why I like bluetooth for syncing my mobile. Hey I am only a confused programmer. Can't expect me to keep all things I need to do in my head. I need all that "head-space" for more important things, like keeping c#, generics, asp.net, entity framework, dynamics, wpf and more. Since the twisted x64 drivers would not install on my computer it was time for some serious googlin'. Stumbled upon a couple of really lame articles before I found a real masterpiece by Gil Kirkpatrick. Don't ask me where this guy got it from though. It's all really simple and I'll just give you my changed files in a zip file in the end.

To keep it a bit shorter than he did you only need to:

  1. Install your freaking x64 drivers
  2. Restart computer
  3. Copy some files from C:\Windows\System32\DriverStore\FileRepository to a directory of your choice like... C:\BT (most of them start with bth, btw and btv)
  4. Change all occurances of NTamd64...1 to NTamd64...3 (one of those -"Don't ask" 's)
  5. Turn Bluetooth on
  6. Go in to device manager, update drivers point to the directory you chose to keep the copies.
  7. Repeat for all other unknown bluetooth devices.

Have fun with your bluetooth devices!

I'm blue(tooth) la da di la da da

Tags:

FAIL

Object reference not set to an instance of an object while using "Add Connection" & "Query Designer"

by Mikael Henriksson 27. January 2009 18:59

It seems like Visual Studio drops a setting needed by OLE DB drivers. The solution to my problems was a simple one but finding it was not!! It took me freaking 3 months to find a way to be able to use Visual Studio (any version) with Access Databases again.

4 months ago I formatted my harddrives and reinstalled everything from scratch. It took only 3 weeks or so before I lost the built in query designer and add connection.

You need to do some simple regediting... I've made a .reg file to do this automatically from now on but I recon noone likes to run .reg files that other people created because of possible security threats so I'll just let you have the way to do it yourselves. :)

  1. Run regedit.exe;
  2. Browse to the location "HKEY_CLASSES_ROOT\CLSID\{F9AE8980-7E52-11d0-8964-00C04FD611D7}" in the tree;
  3. Locate the child node in the tree called "ProgID"
  4. If there is no key you need to create it by Right-clicking the node and select "New > Key";
  5. Enter "ProgID" as the name;
  6. Go to the main window (the one to the right) and double click "(Default)" within ProgID;
  7. Enter the value "MSIDXS.1";

Simple huh? ;) But very useful!

Tags:

Visual Studio

About the author

Life architect specialized in programming

Month List

Widget Twitter not found.

Root element is missing.X