Updates from May, 2013 Toggle Comment Threads | Keyboard Shortcuts

  • danielsaidi 8:06 am on May 14, 2013 Permalink | Reply
    Tags: , , , , encoding, , utf8   

    NExtra 3.2.1.0 

    The newly redesigned NExtra web site.

     

    Yesterday, I added a couple of new features to NExtra and released a new 3.2.1.0 version. You can grab it at GitHub or directly from within Visual Studio, using NuGet.

    The new version features improved command line argument parsing, file encoding detection and funcs for finding assembly files.

    Command line arguments

    Previously, NExtra only contained a modified version of the implementation that can be found at http://www.codeproject.com/KB/recipes/command_line.aspx.

    The new version contains a new, typed parser that returns a CommandLineArguments instance. This new argument class simplifies working with command line arguments, while it still let’s you access the raw argument collection.

    You can find the new classes here.

    File encoding

    In Cloney – another project of mine – I had some issues with file encoding. Some text files were treated as UTF 8 although they were not.

    A contributor – Lars Corneliussen – then added a modified version of the encoding detector that can be found at http://www.architectshack.com/TextFileEncodingDetector.ashx

    I have added this static class, as well as a new IFileEncodingResolver interface and two implementations of this interface. Still, none does the job to 100%, so if you have a great way to detect file encodings, feel free to share.

    You can find the new encoding classes and interfaces here.

    Assembly extensions

    The NExtra.Extensions.Assembly_FileExtensions class now has two methods for finding the folder and file of an assembly’s code base. It is great if you want to find out where a certain program is launched from.

    You can find the methods here.

     

     

     
  • danielsaidi 8:52 am on April 17, 2013 Permalink | Reply
    Tags: , , ,   

    Removing documentation 

    When working with NExtra, I wanted to extract HTML documentation from the source code. To do so, I enabled extracting XML documentation for each project that I wanted to include in the documentation.

    However, when I did check this small button, Visual Studio started to complain about missing documentation for public methods and properties. Instead of just ignoring these warnings (strangely, I want  my source code to be warning- and error free), I then begun adding comments to all public components.

    This is a couple of years ago, and the problem I soon found myself to face, was that I found myself writing comments like this.

    ///<summary>Send an e-mail message.</summary>
    public object SendEmail(...)

    Talk about useless comments. However, I wanted the documentation to be extracted and I did not want the warnings (and disabling warnings for the projects did not always work, either), so I decided to stick with the comments.

    Now, though, I have decided to go through the code base and remove all useless pieces of comments, which is most of them. I put a great deal of effort into writing readable and simple code, so my goal is to just have a class summary for as many classes as possible.

     
  • danielsaidi 9:58 pm on January 24, 2013 Permalink | Reply
    Tags:   

    NExtra 3.0 and NDepend 4.1 

    Returning to work, I am getting back together with the world of .NET, which I so brutally left when going on parental leave, almost a year ago. During that time, I have mostly been working on iOS applications, and created a bunch of them, like Wally, Remembat, Appamini and Deckorama.

    However, it is great to be back, and I started it off by revisiting my good ol’ NExtra project. During the last two weeks, I have created a brand new website for the library and plowed through the code, upgrading the whole enchilada to 3.0.

    The newly redesigned NExtra web site.

    The newly redesigned NExtra web site.

    With this new version in place, I am now finally ready to take a look at the brand new (well, not anymore) NDepend 4. My loooong delay to start experimenting with this great tool (I have had a professional license since summer, thanks to the great NDepend team) has been a big shame for me, but now I will finally get started…

    …and analyze the sh*t out of NExtra 3.0.

    I will sum up my NDepend analysis in a blog post per library. See you then!

     
  • danielsaidi 10:04 am on October 31, 2012 Permalink | Reply
    Tags: , , , visual studio 2012   

    NExtra 3.0 returns 

    NExtra logotype

    Yeah, I have finally understood that official announcements needs to be something like:

    NExtra

    returns
    2013

    So, there you go.

    No, what it’s really about is that I – after almost 6 month away – am returning to the .NET realm. I will revisit my .NET Open Source projects (http://github.com/danielsaidi) and also begin to convert some of my iOS apps (http://saidi.se) to WP.

    One of my babies is the NExtra project (http://danielsaidi.github.com/nextra), which has been a kind of utility box where I’ve put reusable stuff that I have developed in some of my projects. When I have added them to NExtra, I have also tried to make them as abstract as possible, to make it possible for devs to build upon the foundation.

    Although NExtra is a library – you can just refer to it from any .NET project – I mostly just copy stuff from it to my various projects. For instance, I have numerous validation classes as well as an abstract validation interface. Would be a waste to rebuild it for each project I create.

    The next step

    So, what will be the next step for NExtra? Well, for one, I will

    • Increate the version number to 3.0 (boom!)
    • Throw out everything (boom!^2)
    • Rewrite everything (sort of…)

    No, it’s not as crazy as it sounds. I will start of with an entirely new solution, sure, but I will just re-add things from the current version of NExtra, if I find it to still be good and useful. One thing that I will make sure to do, is to add valid abstractions for the lowest denominator, even if it means that implementations only exist at higher levels.

    For one, consider serialization. A very general object serializer interface will exist in the NExtra core DLL, while a System.Web-based JSON implementation will exist in the NExtra.Web DLL. This way, NExtra 3.0 will define a lot of interfaces in the core DLL, that are only implemented in higher levels.

    I will also use the new NDepend v4 (well, it was new when I meant to try it out…now, it’s been out for a while) from scratch to continuously analyze the code I add to NExtra. I will write short blog posts about this as development proceeds.

    I really hope that you join me and give me feedback along the way.

    All the best!

     
  • danielsaidi 11:16 am on August 12, 2012 Permalink | Reply
    Tags: domain, , project   

    Kill your domain darlings 

    Since GitHub offers such a great page service for open source projects, I have decided to let some domains of mine go, where I host the software on GitHub. The way I see it, it is more consistent if the web page for a project is located at the same place as the source code.

    So, for .NExtra, I will make some changes:

    This will, sadly, mean that all public urls to the old NExtra repository will not work from now on. I will change all invalid URLs at this blog and on my site.

    Sometimes, the fact that few people use your things is not all that bad :)

     
  • danielsaidi 1:03 pm on February 22, 2012 Permalink | Reply
    Tags: , boo, , , nuget package explorer, phantom, ,   

    The .NExtra release process, using Phantom/Boo and automatically publishing to NuGet and GitHub 

    In this blog post, I will describe how I manage the .NExtra release process, which involves auto-generating a version-marked zip file and pushing the release to external targets like GitHub and NuGet.

    The problem

    In .NExtra, I used to handle the release process manually. Since a release involved executing unit tests, bundling all files, zipping and uploading the bundle to GitHub, creating new git tags etc. the process was quite time-consuming and error-prone.

    But things did not end there. After adding .NExtra to NuGet, every release also involved refreshing and publishing six NuGet packages. Since I used the NuGet Package Explorer, I had to refresh the file and dependency specs for each package. It took time, and the error risk was quite high.

    All in all, since releasing new versions involved so many steps, I used to release .NExtra quite seldom. Laziness was killing it.

    The solution

    I realized that something had to be done. Unlike at work, where we use TeamCity for all solutions, I found a build server to be a bit overkill. However, maybe I could use a build script for automating the build and release process?

    So with this conclusion, I defined what the script must be able to help me out with:

    • Build and test all projects in the solution
    • Automatically extract the resulting version
    • Create a release folder or zip with all files
    • Create a new release tag and push it to GitHub
    • Create a NuGet package for each project and publish to NuGet

    The only piece of the release process not covered by this process was to upload the release zip to GitHub, but that would be a walk in the park once the build script generated a release zip.

    The biggest step was not developing the build script. In fact, it is quite a simple creation. Instead, the biggest step was to come to the conclusion that I needed one.

    Selecting a build system

    In order to handle my release process, I needed a build system. I decided to go with Phantom, since I use it at work as well. It is a convenient tool (although a new, official version would be nice) that works well, but it left me with an annoying problem, which I will describe further down.

    So, I simply added Phantom 0.3 to a sub folder under the solution root. No config is needed – the build.bat and build.boo (read on) files take care of everything.

    The build.bat file

    build.bat is the file that I use to trigger a build, build a .zip or perform a full publish from the command prompt. I placed it in
    the solution root, and it looks like this.

    @echo off
    
    :: Change to the directory that this batch file is in
    for /f %%i in ("%0") do set curpath=%%~dpi
    cd /d %curpath%
    
    :: Fetch input parameters
    set target=%1
    set config=%2
    
    :: Set default target and config if needed
    if "%target%"=="" set target=default
    if "%config%"=="" set config=release
    
    :: Execute the boo script with input params - accessible with env("x")
    resources\phantom\phantom.exe -f:build.boo %target% -a:config=%config%

     

    Those of you who read Joel Abrahamsson’s blog, probably recognize the first part. It will move to the folder that contains the .bat file, so that everything is launched from there.

    The second section fetches any input parameters. The target param determines the operation to launch (build, deploy, zip or publish) and config what kind of build config to use (debug, release etc.)

    The third section handles param fallback in case I did not define some of the input parameters. This means that if I only provide a target, config will fall back to “release”. If I define no params at all, target will fall back to “default”.

    Finally, the bat file calls phantom.exe, using the build.boo file. It tells build.boo to launch the provided “target” and also sends “config” as an environment variable (the -a:config part).

    All in all, the build.bat file is really simple. It sets a target and config and uses the values to trigger the build script.

    The build.boo file

    The build.boo build script file is a lot bigger than the .bat file. It is also located in the solution root and looks like this:

    import System.IO
    
    project_name = "NExtra"
    assembly_file = "SharedAssemblyInfo.cs"
    
    build_folder = "_tmpbuild_/"
    build_version = ""
    build_config = env('config')
    
    test_assemblies = (
     "${project_name}.Tests/bin/${build_config}/${project_name}.Tests.dll", 
     "${project_name}.Web.Tests/bin/${build_config}/${project_name}.Web.Tests.dll", 
     "${project_name}.Mvc.Tests/bin/${build_config}/${project_name}.Mvc.Tests.dll", 
     "${project_name}.WPF.Tests/bin/${build_config}/${project_name}.WPF.Tests.dll", 
     "${project_name}.WebForms.Tests/bin/${build_config}/${project_name}.WebForms.Tests.dll", 
     "${project_name}.WinForms.Tests/bin/${build_config}/${project_name}.WinForms.Tests.dll", 
    )
     
    
    target default, (compile, test):
     pass
    
    target zip, (compile, test, copy):
     zip("${build_folder}", "${project_name}.${build_version}.zip")
     rmdir(build_folder)
     
    target deploy, (compile, test, copy):
     with FileList(build_folder):
     .Include("**/**")
     .ForEach def(file):
     file.CopyToDirectory("{project_name}.${build_version}")
     rmdir(build_folder)
    
    target publish, (zip, publish_nuget, publish_github):
     pass
     
    
    target compile:
     msbuild(file: "${project_name}.sln", configuration: build_config, version: "4")
     
     //Probably a really crappy way to retrieve assembly
     //version, but I cannot use System.Reflection since
     //Phantom is old and if I recompile Phantom it does
     //not work. Also, since Phantom is old, it does not
     //find my plugin that can get new assembly versions.
     content = File.ReadAllText("${assembly_file}")
     start_index = content.IndexOf("AssemblyVersion(") + 17
     content = content.Substring(start_index)
     end_index = content.IndexOf("\"")
     build_version = content.Substring(0, end_index)
    
    target test:
     nunit(assemblies: test_assemblies, enableTeamCity: true, toolPath: "resources/phantom/lib/nunit/nunit-console.exe", teamCityArgs: "v4.0 x86 NUnit-2.5.5")
     exec("del TestResult.xml")
    
    target copy:
     rmdir(build_folder)
     mkdir(build_folder)
     
     File.Copy("README.md", "${build_folder}/README.txt", true)
     File.Copy("Release-notes.md", "${build_folder}/Release-notes.txt", true)
     
     with FileList(""):
     .Include("**/bin/${build_config}/*.dll")
     .Include("**/bin/${build_config}/*.pdb")
     .Include("**/bin/${build_config}/*.xml")
     .Exclude("**/bin/${build_config}/*.Tests.*")
     .Exclude("**/bin/${build_config}/nunit.framework.*")
     .Exclude("**/bin/${build_config}/nsubstitute.*")
     .ForEach def(file):
     File.Copy(file.FullName, "${build_folder}/${file.Name}", true)
    
    
    target publish_nuget:
     File.Copy("README.md", "Resources\\README.txt", true)
     File.Copy("Release-notes.md", "Resources\\Release-notes.txt", true)
     
     exec("nuget" , "pack ${project_name}\\${project_name}.csproj -prop configuration=release")
     exec("nuget" , "pack ${project_name}.web\\${project_name}.web.csproj -prop configuration=release")
     exec("nuget" , "pack ${project_name}.mvc\\${project_name}.mvc.csproj -prop configuration=release")
     exec("nuget" , "pack ${project_name}.wpf\\${project_name}.wpf.csproj -prop configuration=release")
     exec("nuget" , "pack ${project_name}.webforms\\${project_name}.webforms.csproj -prop configuration=release")
     exec("nuget" , "pack ${project_name}.winforms\\${project_name}.winforms.csproj -prop configuration=release")
     
     exec("nuget push ${project_name}.${build_version}.nupkg")
     exec("nuget push ${project_name}.web.${build_version}.nupkg")
     exec("nuget push ${project_name}.mvc.${build_version}.nupkg")
     exec("nuget push ${project_name}.wpf.${build_version}.nupkg")
     exec("nuget push ${project_name}.webforms.${build_version}.nupkg")
     exec("nuget push ${project_name}.winforms.${build_version}.nupkg")
     
     exec("del *.nupkg")
     exec("del Resources\\README.txt")
     exec("del Resources\\Release-notes.txt")
    
    target publish_github:
     exec("git add .")
     exec('git commit . -m "Publishing ${project_name} ' + "${build_version}" + '"')
     exec("git tag ${build_version}")
     exec("git push origin master")
     exec("git push origin ${build_version}")
    

    Topmost, we see a system import. This will allow us to use System.IO for file operations. After that, I define some variables and a list of test assemblies that I want to test.

    Two variables worth mentioning is the build_version, which is set in the compile step, as well as build_config, which is set by the input parameter defined in build.bat.

    The next section of the file defines all public targets, that are intended to be callable by the user. These map directly to target in build.bat.

    Of course, all targets further down can be called as well – there are no such thing as public or private targets. Still, that would probably not be a very good idea.

    If we look at the public targets, we have:

    • default – Executes “compile” and “test”
    • zip – Executes “compile” and “test”, then creates a zip file
    • deploy – Executes “compile” and “test” then creates a folder
    • publish – Executes “zip”, then publishes to NuGet and GitHub

    If we look at the private targets (that do the real work) we have:

    • compile – Compiles the solution and extract the version number
    • test – Runs the NUnit builtin with the .NExtra test assemblies
    • copy – Copies all relevant files to the temporary build_folder
    • publish_nuget – Pack and publish each .NExtra project to NuGet
    • publish_github – Commit all changes, create a tag then push it

    It is not that complicated, but it is rather much. You could take the bat and boo file and tweak it, and it would probably work for your projects as well.

    However, read on for some hacks that I had to do to get the build process working as smoothly as it does.

    One assembly file to rule them all

    A while ago, I decided to extract common information from each of the .NExtra projects into a shared assembly file.

    The shared assembly file looks like this:

    using System.Reflection;
    // General Information about an assembly is controlled through the following 
    // set of attributes. Change these attribute values to modify the information
    // associated with an assembly.
    [assembly: AssemblyCompany("Daniel Saidi")]
    [assembly: AssemblyProduct("NExtra")]
    [assembly: AssemblyCopyright("Copyright © Daniel Saidi 2009-2012")]
    [assembly: AssemblyTrademark("")]
    // Make it easy to distinguish Debug and Release (i.e. Retail) builds;
    // for example, through the file properties window.
    #if DEBUG
    [assembly: AssemblyConfiguration("Debug")]
    #else
    [assembly: AssemblyConfiguration("Retail")]
    #endif
    // Version information for an assembly consists of the following four values:
    //
    // Major Version
    // Minor Version 
    // Build Number
    // Revision
    //
    // You can specify all the values or you can default the Build and Revision Numbers 
    // by using the '*' as shown below:
    [assembly: AssemblyVersion("2.6.3.4")]
    [assembly: AssemblyFileVersion("2.6.3.4")]

    The file defines shared assembly information like version, to let me specify this once for all projects. I link this file into each project and then remove the information from the project specific assembly info file.

    Since the .NExtra version management is a manual process (the way I want it to be), I manage the .NExtra version here and parse the file during the build process to retrieve the version number. The best way would be to use System.Reflection to analyze the library files, but this does not work, since Phantom uses .NET 3.5.

    I tried re-compiling Phantom to solve this, but then other things started to crash. So…the file parse approach is ugly, but works.

    Tweaking NuGet

    After installing NuGet, typing “nuget” in the command prompt will still cause a warning message to appear, since “nuget” is unknown.

    To solve this, either add the NuGet executable path to PATH or be lazy and use the nuget.exe command line bootstrapper, which finds NuGet for you. You can download it from CodePlex or grab it from the .NExtra Resources root folder.

    Regarding each project’s nuspec file, they were easily created by calling “nuget spec x” where x is the path to the project file. A nuspec file is then generated. I then added some information that cannot be extracted from the assembly, like project URL, icon etc. for each of these generated spec files.

    Conclusion

    This post became a rather long, but I hope that it did explain my way of handling the .NExtra release process.

    Using the build script, I can now call build.bat in the following ways:

    • build – build and test the solution
    • build zip – build and test the solution and generate a nextra.<version>.zip file
    • build deploy – build and test the solution and generate a nextra.<version>.zip folder
    • build publish – the same as build zip, but also publishes to NuGet and GitHub.

    The build script has saved me immense amount of work. It saves me time, increases quality by reducing the amount of manual work and makes releasing new versions of .NExtra a breeze.

    I still have to upload the zip to the GitHub download area, but I find this to be a minimum task compared to all other steps. Maybe I’ll automate this one day as well, but it will do for now.

    I strongly recommend all projects to use a build script, even for small projects where a build server is a bit overkill. Automating the release process is a ticket to heaven.

    Or very close to that.

     
    • Markus Johansson 10:07 am on July 16, 2013 Permalink | Reply

      Great post! Looks as a really nice release script! Thanks for sharing your experiance!

      • danielsaidi 8:33 am on July 20, 2013 Permalink | Reply

        Thanks! :) Once all pieces are in place, publishing new releases is a breeze.

  • danielsaidi 10:13 pm on December 6, 2011 Permalink | Reply
    Tags:   

    .NExtra 5.2.1.0 and 5.2.2.0 

    I have not blogged that frequently lately, but that does not mean that I do not write code :)

    Besides putting together new, small hobby projects like Cloney and Facadebook and working on two yet not released web sites, I have also put more stuff into .NExtra and polished already existing stuff. 2.5.1.0 was released November 27 and 2.5.2.0 juuuust now. Here are the news:

    2.5.1.0

    I have fixed a bug in NExtra.Mvc.Testing.ControllerExtensions. The CallWithModelValidation method used to assume that the MemberNames property of each error did always contain an element. However, for Compare validators, this is not the case.

    The NExtra.Localization.HieararchicalResourceManagerFacade, which can be used to translate resource files hierarchically, now has two constructors instead of the previous one with one required and one optional parameter. I will probably remove optional parameters elsewhere in future versions.

    In order to make client-side validation easier to use with all the validation attributes in NExtra.ValidationAttributes, every regex-based attribute now expose its internal expression, so that models can use either the attribute directly or embed the expression in a RegularExpressionAttribute (which works client-side). It is important to note that no NExtra.ValidationAttributes inherit from OptionalRegularExpressionAttribute from now on. These classes now inherit directly from RegularExpressionAttribute, which makes them OPTIONAL. If you need them to be required, combine them with a Required attribute. Quite a breaking change, I know, but I just felt like it :)

    The NExtra.Mvc.ActionFilters.OutputModelAttribute has been renamed to JsonForQueryStringAttribute. It’s quite more obvious. If you use the old one, just switch it out for this new one. What the attribute does is to output the view model as JSON if a certain query criteria is met.

    The NExtra.Mvc.Extensions.WebViewPageExtensions has been rewritten to use the HtmlHelper classes for local and global resources. Both alternatives can be used, although only one should really be needed.

    2.5.2.0

    I have added a new ValidationAttributes.PhoneNumberAttribute class. It is really basic and allows an intial, optional +, followed by a set of digits and spaces, followed by an optional -, then followed by a last set of digits and spaces. If anyone has a better regex, let me know.

    A brand new Cache section has been added to the NExtra project. It has a basic ICache interface, a really simple dictionary cache and a MemoryCache facade. NExtra.Web has a Cache section as well, with an IHttpRuntimeCache interface and a HttpRuntime.Cache facade.

    The NExtra.Extensions.ObjectExtensions class has a new non-generic clone method that returns object instead of a certain type.

    I have adjusted the Nextra.Web.Html5ElementConverter class so that it adds no extra content to the end tag. It can now be fully used to convert HTML5 elements to HTML4 versions for browsers that do not support HTML5 elements. Thanks, Petter :)

    Finally, I have decided to let the demo section rot. The unit test suite and the source code should be enough for developers who want to learn .NExtra. Still, if anyone wants to keep the demos in good shape, feel free to do so and push the changes to the public repo.

     
  • danielsaidi 1:43 pm on October 20, 2011 Permalink | Reply
    Tags: , , , eventargs, HTML helpers, logging, membership, process, roles   

    .NExtra 2.5.0.0 

    The .NExtra logotype

    I have finally manage to bundle up .NExtra for a new release. The new version number is 2.5.0.0 and it can be downloaded here.

    Working with the new release also included a brand new web site, a brand new project site, a NuGet package collection, updated online documentation etc.

     

    Web site

    A screenshot of the .NExtra web site

    A screenshot of the .NExtra web site


    The web site is really basic, but features some project information as well as links to download, online documentation, issue handling etc. It will soon feature online demos as well, but I am still working on upgrading the demo application that comes with the library.

     

    Project site

    A screenshot of the .NExtra project site

    A screenshot of the .NExtra project site

    The project site is where you will find the latest code, as well as pre-compiled bundles, issue handling etc. For now, it is the main communication channel.

     

    NuGet

    The  new version of .NExtra (the first official) is also available as NuGet packages. To download them, just use the NuGet Package Manager from within Visual Studio or grab them here.

     

    Documentation

    The latest documentation can from now on be found here. I trieeed to style it a bit, but this is as good as it gets, at least for now. If you know how to tweak Doxygen to customize the HTML output, please let me know.

     

    Features

    The 2.5.0.0 release contains several new features, like a new MVC helper, logging utilities, a generic event arguments, a (borrowed) command argument parser, several extension method additions etc. So, there is a some new stuff to play around with.

    The new, generic EventArgs class is a generic version of the native EventArgs class. Use it to attach a typed object to your arg.

    The new CommandLineArgumentParser class is a new, interface-based version of a nice implementation that can be found here. Use it to easily parse arguments that are sent to an application.

    The new Logging namespace contains a few new classes, enums and interfaces that can be used when working with logging.

    The new IConsole and ConsoleFacade are (so far) small and contains two write methods for working towards the Console. I use them in a private project, so they only has methods that I use, for now.

    The same goes for Diagnostics.ProcessFacade and IProcess. They are rather small, and can be used for working toward the Process class. They should probably be extended as well.

    I have added a couple of new extension classes to the base Extensions namespace. I have also added methods to already existing classes.

    The Web.Security.MembershipFacade has been extended to be a more complete facade for the Membership and MembershipUser classes.

    The new Mvc.HtmlHelpers.FormBlockForHelper class can wrap a form element (EditorFor, TextAreaFor etc.) in a structure with one div with a LabelFor and one with the provided editor as well as an editor-bound ValidationMessageFor. This will drastically reduce the amount of code that you will have to write when creating model-bound forms.

    The new Mvc.HtmlHelpers.Conditional HTML helper can be used to output a value out of two possible ones, depending on a bool expression. It can be used to avoid having to write all those nasty if-statements in your views.

     
  • danielsaidi 3:23 pm on September 30, 2011 Permalink | Reply
    Tags: ,   

    .NET Extensions => NExtra 

    I have decided to rename the .NET Extensions project to NExtra. The project will be hosted on GitHub instead of Google Code.

    I decided to change the name to NExtra, since .NET Extensions is very general and says nothing about the library at all, except giving the wrong impression that it only contains extension methods, which it indeed does not.

    I decided to switch from Google Code to GitHub, since I enjoy working with git and find GitHub to be a better alternative for my various source code projects. Google Code has been great, but it’s time to move on.

    Hopefully, I will be able to find and adjust all old references to the .NET Extensions project. I will also create a simple web site for the project, complete with documentation, demos etc. Time is, as always, an issue, but I will try to get it done shortly. Until I do, I will at least create a nice landing page…possibly without the “nice” :)

    I will begin going through this blog after invalid references once I have finished the landing page.

     
  • danielsaidi 4:49 pm on August 28, 2011 Permalink | Reply
    Tags: , EditorBlockFor, EditorFor, HTML helper, LabelFor,   

    EditorBlockFor HTML helper 

    In ASP.NET MVC, I think that Microsoft has done a great job with the various HTML helpers that can be used in form context, such as LabelFor, EditorFor, ValidationMessageFor etc.

    However, despite these great helpers, the HTML still tend to become rather tedious and repetitive.

    For instance, the following HTML generates a form that can be used t0 create groups in a web application that I am currently working on:

        @using (Html.BeginForm())
        {
            @Html.ValidationSummary(true)
    
            <div class="editor-label">
                @Html.LabelFor(model => model.Name)
            </div>
            <div class="editor-field">
                @Html.EditorFor(model => model.Name)
                @Html.ValidationMessageFor(model => model.Name)
            </div>
    
            <div class="editor-label">
                @Html.LabelFor(model => model.CollectionName)
            </div>
            <div class="editor-field">
                @Html.EditorFor(model => model.CollectionName)
                @Html.ValidationMessageFor(model => model.CollectionName)
            </div>
    
            <div class="form-buttons">
                <input type="submit" value="@this.GlobalResource(Resources.Language.Create)" />
            </div>
        }

    That is quite a lot of code for handling two single properties…and the two editor blocks look rather similar, don’t you think?

    I therefore decided to write a small HTML helper extension method – EditorBlockFor – that can be used to generate an editor block (label, editor and validation message).

    Using this new helper, the resulting form becomes a lot shorter and a lot easier to handle:

        @using (Html.BeginForm())
        {
            @Html.ValidationSummary(true)
            @Html.EditorBlockFor(model => model.Name);
            @Html.EditorBlockFor(model => model.CollectionName);
    
            <div class="form-buttons">
                <input type="submit" value="@this.GlobalResource(Resources.Language.Create)" />
            </div>
        }

    As you see, the method is only to be used if you want to follow the conventions that are used for auto-generated ASP.NET MVC form code. But if you do…you can save a lot of keystrokes.

    I am not that familiar with the MvcHtmlString type, which the native methods return, so returning an IHtmlString instead of MvcHtmlString could be a big no no that I do not know about. Please let me know if I have ruined the order of the universe.

    I will add this helper to .Nxtra project and put it up for download as soon as I find the time. Until then, feel free to grab the code here.

     
c
Compose new post
j
Next post/Next comment
k
Previous post/Previous comment
r
Reply
e
Edit
o
Show/Hide comments
t
Go to top
l
Go to login
h
Show/Hide help
shift + esc
Cancel
Follow

Get every new post delivered to your Inbox.