Gunnar Peipman's ASP.NET blog

ASP.NET, C#, SharePoint, SQL Server and general software development topics.

Sponsors

News

 
 
 
DZone MVB

Links

Social

August 2009 - Posts

GetValue<T>() extension method for RegistryKey class

I needed some elegant method to read registry values in my Live Writer Delicious bookmarks plug-in. RegistryKey has GetValue() method but it returns values as object. I wrote generic version of GetValue() as RegistryKey extension method. It returns you specified value from key and converts it to type you ask. If conversions are not successful then default value of given type will be used.

I have two overloads for GetValue<T>(). First of them wants only value name to be specified. Second one expects also default value that is returned in the case of problems. I give some credits to Tony Wright whose blog entry How to add a ToNumber C# language extension method to the String class calling TryParse using reflection gave me some directions.

Here are my extension methods in C# and VB.NET. Don’t forget to import Microsoft.Win32 namespace.

C#

public static T GetValue<T>(this RegistryKey key, string name)

{

    return key.GetValue<T>(name, default(T));

}

 

public static T GetValue<T>(this RegistryKey key, string name,
                            T defaultValue)

{

    var obj = key.GetValue(name, defaultValue);

 

    if (obj == null)

        return defaultValue;

 

    try

    {

        return (T)obj;

    }

    catch(InvalidCastException)

    {

    }

 

    if (typeof(T) == typeof(string))

    {

        obj = obj.ToString();

        return (T)obj;

    }

 

    var types = new[]{typeof(string),typeof(T).MakeByRefType()};

 

    var method = typeof (T).GetMethod("TryParse", types);

    if (method == null)

        return defaultValue;

 

    var valueString = obj.ToString();

    T value = defaultValue;

    var params = new object[] {valueString, value};           

 

    method.Invoke(obj, params);

    return (T)methodParams[1];

}


 
VB.NET

<System.Runtime.CompilerServices.Extension()> _

Public Function GetValue(Of T)(ByVal key As RegistryKey, ByVal name As String) As T

    Return key.GetValue(Of T)(name, Nothing)

End Function

 

<System.Runtime.CompilerServices.Extension()> _

Public Function GetValue(Of T)(ByVal key As RegistryKey, ByVal name As String, ByVal defaultValue As T) As T

    Dim obj = key.GetValue(name, defaultValue)

 

    If obj Is Nothing Then

        Return defaultValue

    End If

 

    Try

        Return DirectCast(obj, T)

    Catch generatedExceptionName As InvalidCastException

    End Try

 

    If GetType(T) Is GetType(String) Then

        obj = obj.ToString()

        Return DirectCast(obj, T)

    End If

 

    Dim paramTypes = New Type() {GetType(String), GetType(T).MakeByRefType()}

 

    Dim method = GetType(T).GetMethod("TryParse", paramTypes)

    If method Is Nothing Then

        Return defaultValue

    End If

 

    Dim valueString = obj.ToString()

    Dim value As T = defaultValue

    Dim methodParams = New Object() {valueString, value}

 

    method.Invoke(obj, methodParams)

    Return DirectCast(methodParams(1), T)

End Function


Example

And here is my little example in C# and VB.NET.

C#

var softKey = Registry.CurrentUser.OpenSubKey("Software");

var myKey = softKey.OpenSubKey("MyAppSettings");

 

showTitle.Checked = myKey.GetValue<bool>("ShowTitle",true);

showDescr.Checked = myKey.GetValue<bool>("ShowDescriptions");


 
VB.NET

Dim softKey As RegistryKey

Dim myKey As RegistryKey

 

softKey = Registry.CurrentUser.OpenSubKey("Software")

myKey = softKey.OpenSubKey("MyAppSettings")

 

showTitle.Checked = myKey.GetValue(Of Boolean)("ShowTitle", True)

showDescr.Checked = myKey.GetValue(Of Boolean)("ShowDescriptions")


That’s it. If you know better solution for reading registry keys or you find bugs here then please feel free to drop me a line. All your feedback is very welcome.


kick it on DotNetKicks.com pimp it Progg it 顶 Shout it
Posted: Aug 20 2009, 01:37 PM by DigiMortal | with 8 comment(s)
Filed under: ,
Bookmarks2LiveWriter: Live Writer plug-in for serious bloggers

Bookmarks2LiveWriter is Windows Live Writer plug-in that is targeted to serious bloggers who also publish bookmarks postings. Bookmarks2LiveWriter lets you download bookmarks for given date range from Delicious and inserts them to current posting. Users can remove unwanted bookmarks and format bookmarks list before inserting it. Bookmarks2LiveWriter is released under GPL. Installer and source code are freely available to everybody.

For live example check out my previous blog entry Links 2009-08-19.

Features

bookmarks2livewriter-groupbytag-cap-upper
 
bookmarks2livewriter-result

Click on images to enlarge them.

Current release, versioned as v0.2.0.0 beta, has following features:

  • Download bookmarks from Delicious.
  • Filter bookmarks by date range.
  • Before publishing remove bookmarks you don't want to show in bookmarks list.
  • Group bookmarks by first tag or publishing date.
  • Create new group for tags and dates which have a single bookmark and give a custom title to this group.
  • Show bookmark descriptions in list.
  • Show bookmarks as unformatted linked list.
  • Show bookmarks as bulleted list.
  • Show bookmarks as numbered list.
  • Capitalize first letter of bookmark title.
  • Create uppercase titles for bookmark titles shorter than four characters.
  • Show tag name or date after groups with single bookmark.

I have already planned some powerful features for future releases. Current version is out there to let users start using Bookmarks2LiveWriter and to get some feedback from community. Next release will have nice bookmarks organizer, data caching (yes, you can work offline too) and some other nice things.

Bookmarks2LiveWriter links

  1. Bookmarks2LiveWriter homepage
  2. Feature list
  3. Screenshots
  4. Development log (information about current, past and future releases)

If you find bugs then please report them to issue tracker. If you want to give some other feedback, ask questions, share your ideas or request features then please use our discussion board. All your feedback is very welcome and I try to help you as much as I can.

Happy bookmarking!


kick it on DotNetKicks.com pimp it
Links 2009-08-19

JQuery and web development

Mobile

Sharepoint

Social Networks

Software

Programming

Other stuff

Follow me @ Twitter

I exist also in Twitter. For some time already. My username is gpeipman. You can find my account here:

http://twitter.com/gpeipman

My tweeting topics (besides usual what-am-I-doing) are my new blog entries, hot technology news and other interesting findings. If you like my writings here or you want to discuss with me or you are serious techno-freak then feel free to follow me at Twitter! :)

Posted: Aug 19 2009, 02:12 AM by DigiMortal | with no comments
Filed under:
.Net Framework 4.0: C# and optional arguments and named parameters

C# 4.0 supports optional method arguments. Related to this is support for named parameters in function calls. For us it makes easier to use methods which have long argument list. It also introduces some new dangers which may lead us to messy and hard to understand code. In this code I will show how to use optional arguments and give some hints how to avoid messy code.

I wrote simple application to illustrate default values and their usage.


class Program

{

    static void Main(string[] args)

    {

        Console.WriteLine(GetArguments("one"));

        Console.WriteLine(GetArguments("one", "four"));

        Console.WriteLine(GetArguments("one", "four", "five"));

        Console.WriteLine(GetArguments("one", third:"five"));           

 

        Console.WriteLine("Press any key to exit...");

        Console.ReadLine();

    }

 

    private static string GetArguments(string first,
                string
second = "two", string third="three")

    {

        return first + " " + second + " " + third;

    }

}


csharp-optional-arguments-outputExample (not exact) output of this program is shown on image on right.

First three calls to GetArguments() are not something crucial and they follow current C# syntax.

Fourth call introduces named parameter. Notice how we are giving value to first and third argument. Syntax is very simple: parameter:value.

Use carefully

Optional arguments are widely used in VBA for long time. Although they make life a little bit easier for programmers (you don’t have to repeat default values in your method calls) there will be always danger that optional arguments are overused.

Too long argument lists refers to the need of parameter object (refactoring method called Introduce Parameter Object). Parameter object may also carry default values because you can assign initial values to object attributes and properties.

Of course, it is up to you and depends on context if you want to use method with many arguments or parameter object. If you know pitfalls then it is easier for you to make decisions.


kick it on DotNetKicks.com pimp it Progg it 顶 Shout it
Posted: Aug 19 2009, 02:11 AM by DigiMortal | with 9 comment(s)
Filed under: ,
Developing Delicious applications

I am developing a little piece of software that interacts with Delicious through HTTP API. Using Delicious API puts you one responsibility – use their service carefully. Don’t flood it and don’t stress it some other way. In this posting I will show you how to get bookmarks from Delicious and how to use their service without stressing it pointlessly.

Why Delicious? Because I keep my bookmarks there. If you are interested in my selection you can always check out what new bookmarks I have. I try to add new bookmarks as often as I find something useful.

Connecting to Delicious

I am using very simple custom class to query my bookmarks at Delicious. My class connects to Delicious using my username and password. As my class is still very yound it has some not so nice things – like hardcoded UrlPrefix. But it is okay for now.


public class DeliciousClient

{

    private readonly string _userName;

    private readonly string _password;

 

    private string UrlPrefix = "https://api.del.icio.us/v1/";

 

    public DeliciousClient(string userName, string password)

    {

        _userName = userName;

        _password = password;

    }

 

    public IList<Bookmark> GetBookmarks(DateTime fromDate,
                                        DateTime toDate)

    {

        var url = "posts/all?";

        url += "fromdt=";
        url += fromDate.Date.ToString("yyyy-MM-ddThh:mm:ssZ");

        url += "&todt=";
        url += toDate.Date.ToString("yyyy-MM-ddThh:mm:ssZ");

 

        string result = RequestData(url);


        // Parse XML and return list of bookmarks

    }

 

    private string RequestData(string uri)

    {           

        using (var client = new WebClient())

        {

            var credential = new NetworkCredential(_userName,
                                  _password);

            client.Credentials = credential;

            var url = UrlPrefix + uri;

            var result = client.DownloadData(url);

 
           return Encoding.Default.GetString(result);

        }           

    }

}


Using this code I am able to connect to Delicious and run my queries to get data. But if I connect to often then Delicious handles my requests as flooding and stops access for hours. With little efforts we are able to avoid it.

Caching queries

To avoid real connections to Delicious we can cache query results for us. Just perform there steps:

  1. Put break-point somewhere where you are able to get pure XML response (RequestData method is good candidate).
  2. Connect to Delicious through your code.
  3. When break-point is hit copy the XML result to clipboard.
  4. Stop your program.
  5. Create new XML-file called DeliciousResponse.xml to bin\Debug folder.
  6. Paste XML to this file and save it.

Now a little trick. We have Debug and Release configurations available out-of-box in Visual Studio. Let’s use them now. Debug configuration defines DEBUG constant for preprocessor. We can therefore write a code that is executed if DEBUG is there.

If DEBUG is defined we will read data from XML-file we created previously. The code is here for GetBookmarks method.


public IList<Bookmark> GetBookmarks(DateTime fromDate,
                                    DateTime toDate)

{

    var url = "posts/all?";

    url += "fromdt=";
    url += fromDate.Date.ToString("yyyy-MM-ddThh:mm:ssZ");

    url += "&todt=";
    url += toDate.Date.ToString("yyyy-MM-ddThh:mm:ssZ");

 

    string result;

#if DEBUG

    using (var reader = new StreamReader(File.OpenRead
                            ("DeliciousResponse.xml")))

    {

        result = reader.ReadToEnd();

    }

#else

    result = RequestData(url);

#endif


    // Parse XML and return list of bookmarks

}


Now you can run your code using Debug configuration and avoid requests to Delicious. If you need real data and communication with Delicious you can switch your project to Release configuration. I think it is very simple and powerful solution for now (of course, I will change my mind when requirements to my software change).

That’s it. If you write something cool for Delicious then let also community to know about it.


kick it on DotNetKicks.com pimp it Progg it 顶 Shout it
vote it on WebDevVote.com
Displaying custom HTML in WebBrowser control

I am using WebBrowser control to show preview of automatically generated HTML. Users can select options and preview pane reflects those changes automatically. WebBrowser control has some problems that have been here for years already. Here is my example about how to show custom HTML in WebBrowser control.

Problem

When we look at methods and properties of WebBrowser control our common sense tells us that something like this should work (VB.NET users: delete “;” after this line):


webBrowser1.DocumentText = "some text here";


And it works - only once. All subsequent assignments change nothing. When we try to refresh WebBrowser control we get only white are. Setting AllowNavigation property to true – some guys suggest it – has no effect also.

Solution

To get all assignments works after first one we need to navigate to some page. about:blank is good candidate because it “exists” also in local machine for sure. And that’s not enough – we need to write something to document. After that we can show our custom HTML.

C#

private void DisplayHtml(string html)

{

    webBrowser1.Navigate("about:blank");

    if (webBrowser1.Document != null)

    {

        webBrowser1.Document.Write(string.Empty);

    }

    webBrowser1.DocumentText = html;

}


VB.NET

Private Sub DisplayHtml(ByVal html As String)

    webBrowser1.Navigate("about:blank")

    If webBrowser1.Document IsNot Nothing Then

        webBrowser1.Document.Write(String.Empty)

    End If

    webBrowser1.DocumentText = html

End Sub


NB! You should set AllowNavigation property to true before you deal with contents shown to users.

Keeping users on generated page

Now we can show HTML correctly and everything seems to be okay. But are we finished? Answer is yes if we want users to be able to follow the links we show to them and no if we want to keep users on generated page.

Currently we allowed navigation because otherwise we cannot move to about:blank. We have to allow this navigation and disable all other navigation. Fortunately there is Navigating event of WebBrowser. In Navigating event we can do our filtering.

C#

private void webBrowser1_Navigating(object sender,

        WebBrowserNavigatingEventArgs e)

{

    if (e.Url.ToString() != "about:blank")

        e.Cancel = true;

}


VB.NET

Private Sub webBrowser1_Navigating(ByVal sender As Object, _

            ByVal e As WebBrowserNavigatingEventArgs)

    If e.Url.ToString() <> "about:blank" Then

        e.Cancel = True

    End If

End Sub


So, that’s it. We can now display our custom HTML in WebBrowser control as many times as we want. If you have some better trick then please let me know!


kick it on DotNetKicks.com pimp it Progg it 顶 Shout it
SPGenerateFileDefinitions – create XML-definitions for files fast

I wrote simple utility that generates File and ElementFile blocks for images that are included in site definition. I am programming nicely designed community portal on SharePoint and there are so much files that it is easier to automate XML definitions creation process, at least partly. I am also pretty sure that image files may come and go during project and we have to modify or recreate those definitions. So here is my simple utility that makes dirty work for me.

spgeneratefiledefinitionsI named my little utility as SPGenerateFileDefinitions and it is available in CodePlex.

Screenshot here shows what my utility outputs. You can click on image to enlarge it. Currently it is built around images but if somebody needs I can modify it. No problem.

Using SPGenerateFileDefinitions is easy. Just download executable from project page, run it, show the folder where you files exist and press button Create XML. When File and ElementFile blocks are done utility tells you how much files there were. You can use this information to compare file counts – it may be useful. For us it is useful. :)

If you have any questions or suggestions then please feel free to drop me a line in project discussion site. If you find any bugs or face any problems then please report these to issue tracker.


kick it on DotNetKicks.com pimp it Progg it 顶 Shout it
SharePoint problem: moderation comment is not saved

I solved last week one pretty cool mystery in SharePoint. I have form that users use to make some specific changes to list items. When all the fields on form are filled then user clicks save button. Changes are saved to list item and list item is automatically accepted. Status change is made through ModerationInformation property of SPListItem. Everything seemed to work except one little thing – moderation status comment was not saved.

It took me couple of hours to figure out what is going on. This time, again, Reflector saved my ass. I followed the method calls from list item update to SPRequest methods (find out more by reading brilliant code posting Understanding SharePoint: SPRequest by Hristo Pavlov) that Reflector wasn’t able to disassemble. As soon as I saw request I got the correct answer: Response.

Take a look at this code fragment.


// initialization code

 

item.ModerationInformation.Status = SPModerationStatusType.Approved;

item.ModerationInformation.Comment = "Accepted";

item.Update();

 

// some more code

 

Response.Redirect(returnUrl, true);


You see that Response is forced to end using second argument of Response.Redirect() method. This was the source of problem. After using Response.Redirect with one argument the problem was solved because Response was not forced to end.

I hope this information saves some hours of work for world. :)


kick it on DotNetKicks.com pimp it Progg it 顶 Shout it
vote it on WebDevVote.com
Posted: Aug 10 2009, 01:23 PM by DigiMortal | with 7 comment(s)
Filed under:
Windows 7: Links for developers

As Windows 7 is now available to MSDN and TechNet users it is time to give some references for developers who are interested in Windows 7 software development.

  • Microsoft Windows SDK for Windows 7 and .NET Framework 3.5 SP1 (ISO)
    The Windows SDK for Windows 7 and .NET Framework 3.5 SP1 provides the documentation, samples, header files, libraries, and tools (including C++ compilers) that you need to develop applications to run on Windows 7 and the .NET Framework 3.5 SP1. To build and run .NET Framework applications, you must have the corresponding version of the .NET Framework installed. This SDK is compatible with Visual Studio® 2008, including Visual Studio Express Editions, which are available free of charge.
     
  • Windows® API Code Pack for Microsoft® .NET Framework
    The Windows® API Code Pack for Microsoft® .NET Framework provides a source code library that can be used to access some new Windows 7 features (and some existing features of older versions of Windows operating system) from managed code. These Windows features are not available to developers today in the .NET Framework.
     
  • Windows 7 Training Kit For Developers
    The Windows 7 Training Kit for Developers includes presentations, hands-on labs, and demos designed to help you learn how to build applications that are compatible with and shine on Windows 7

If you are upgrading your system from Windows Vista and you have Visual Studio 2010 Beta 1 then please read Scott Hanselman’s blog entry Vista Users - Uninstall Visual Studio 2010 Beta 1 before upgrading to Windows 7.


kick it on DotNetKicks.com pimp it Progg it 顶 Shout it
More Posts Next page »