NecroNetTookit v1.0.0 prerelease

Posted on Mar 31, 2012

After experiences gained during my last and current project, I made a lot of changes and improvements to NecroNetToolkit, and also a few new features. I’m not done quite yet, but I wanted to put the new version out there, since the stuff that’s left to do is mostly unit tests and documentation.

I will be rewriting most of the wiki pages and writing new unit tests when I get the chance. As far as new functionality is concerned, the most I will do for this version is add some general extension methods. However I have some plans to add some new features after the conclusion of the development of my current project.

A bit of warning though: this release is NOT backwards compatible and contains a lot of BREAKING CHNAGES to the API.

Change log (raw version) here: http://dl.dropbox.com/u/52462718/NecroNetToolkit%20v1.0.0%20changes.png

View comments (0)

Get emails from SharePoint 2010 people editor

Posted on Sep 21, 2011

I’ve recently implemented a feature that was supposed to send emails to all users selected by multi people picker in SharePoint, in one of our projects. Of course SharePoint groups as well as AD groups could be selected too.

It’s not extremely hard to do, but it’s handy to have it up for other coworkers and peoples use.

public static class SPFieldUserValueCollectionExtensions
{
    public static IEnumerable<string> GetAllEmails(this SPFieldUserValueCollection collection, SPWeb web)
    {
        var emails = new HashSet<string>();

        foreach (var item in collection)
        {
            if (item.User == null)
            {
                try
                {
                    // is it a SharePoint group?
                    var group = web.SiteGroups.GetByID(item.LookupId);
                    emails.AddEmailsFromSPGroup(group);
                }
                catch
                {
                    // ad group
                    var group = web.EnsureUser(item.LookupValue);
                    emails.AddIfNotNull(group.Email);
                }
            }
            else
            {
                emails.AddIfNotNull(item.User.Email);
            }
        }

        return emails;
    }

    private static void AddEmailsFromSPGroup(this HashSet<string> emails, SPGroup group)
    {
        if (!string.IsNullOrEmpty(group.DistributionGroupEmail))
        {
            emails.Add(group.DistributionGroupEmail);
        }
        else
        {
            foreach (SPUser user in group.Users)
            {
                emails.AddIfNotNull(user.Email);
            }
        }
    }

    private static void AddIfNotNull(this HashSet<string> set, string s)
    {
        if(!string.IsNullOrEmpty(s))
        {
            set.Add(s);
        }
    }
}

So basically you iterate through a SPFieldUserValueCollection, checking if User property is null first. If it is, it means one of two things: either it’s a SharePoint group or it’s an AD group that wasn’t loaded into SharePoint yet. If the group is found in SiteGroups, it’s a SharePoint group, otherwise AD group must be loaded using EnsureUser method.

Also for SharePoint group, if DistributionGroupEmail property is not set, the code drills into the group, and adds emails of all members.

One thing this method doesn’t do is drill into AD groups when email is not set on that group. While it would be possible to do this, it is way easier to convince customer to setup distribution emails on AD groups or pass it onto your IT department (or theirs).

If your data doesn’t come from built in people picker field, but rather from custom form with people picker, you can parse content into SPFieldUserValueCollection like this:

var mailUsers = new SPFieldUserValueCollection();
mailUsers.AddRange(from PickerEntity entity in UsersEditor.ResolvedEntities
             select
             new SPFieldUserValue(web, Convert.ToInt32(entity.EntityData["SPUserID"] ??
                                            entity.EntityData["SPGroupID"]),
                                  (string) entity.EntityData["AccountName"]));

emails = mailUsers.GetAllEmails(elevatedWeb).ToList();

Run with elevated privileges to access the SiteGroup property.

View comments (0)

Announcing CodeCaml - write SharePoint queries with C#

Posted on Aug 31, 2011

If you are a SharePoint developer, and hate having XML/HTML or any other kind of markup/magic string then keep reading. If not, keep reading anyway, you might change your mind ;).

One of these messy things in SharePoint are CAML queries. Since LINQ to SharePoint is far from being reasonably usable, you can’t really avoid them. And they make my code look ugly. So I developed a tool, which can be used to generate CAML queries and statements with C# code.

This is an example of how you would write a simple query using CodeCaml:

query.Query = CQ.Where(CQ.Eq.FieldRef(fieldId).Value(value));

That’s the same as:

query.Query = string.Format("<Where><Eq><FieldRef ID='{0}' /><Value Type='Text'>" + 
                            "{1}</Value></Eq></Where>", fieldId, value);

You can read more on syntax on the project wiki.

Check the source code on github or start using immediately with NuGet.

Disclaimer: The tool is in BETA stage at the moment, so use in production at your own risk. I would also appreciate any feedback.

View comments (0)

Enable or disable ribbon custom action based on user permissions

Posted on Jul 25, 2011

It’s been a while since I wrote something. That’s because I’ve been busy at my new job (student no longer :() learning SharePoint 2010. Needless to say it was quite the transition from nice, neat, clean way I was used to from MVC to SharePoint where, well… a lot of thing don’t work and you have to ‘hack’ a lot ;). But enough about my issues you don’t need to be concerned with. Let’s have a look at the problem at hand.

Consider following scenario: you have to develop a custom action (a ribbon button), that will only be enabled for certain content type and only for a user who has the permission to edit that particular item (each item in the list can have different permissions). This button will be in a list view ribbon (e.g. AllItems.aspx). As you highlight different items, that button will change state to either enabled or disabled (greyed out) based on that criteria.

Creating the button itself is easy enough (nothing is easy in SharePoint, but easy enough). Just create an empty element and write CAML for custom ribbon button:

<?xml version="1.0" encoding="utf-8"?>
<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
    <CustomAction Location="CommandUI.Ribbon" Id="Ribbon.Documents.EditCheckout.DoSomething">
        <CommandUIExtension>
            <CommandUIDefinitions>
                <CommandUIDefinition Location="Ribbon.Documents.EditCheckout.Controls._children">
                    <Button Id="Ribbon.Documents.EditCheckout.DoSomethingButton"
                        Image32by32="/_layouts/images/ctor32.png" TemplateAlias="o1"
                        Command="DoSomething_Command"
                        LabelText="Do something"
                        ToolTipTitle="Do something" ToolTipDescription="Does something" />
                </CommandUIDefinition>
            </CommandUIDefinitions>
        </CommandUIExtension>
    </CustomAction>
</Elements>

That places the button to EditCheckout ribbon group of document libraries.

Now for the harder part. First I tried to check all criteria for enabling the button in javascript (canHandleCommand function in my page component). I could find out how many items was selected (and enable the button only if a single item was selected) and I could also find out what is the content type of currently selected item. What I couldn’t find out was how to check if user has some permission for that item. I asked around in my company, at stack overflow, but nobody seemed to know what to do.

One suggestion I got was to use Rights attribute on the custom action, but that doesn’t work with the page component (the canHandleCommand would override it) and I don’t think it can change the state of the button as you click through the items (not completely sure though).

After a few days I came up with a ‘hack’ (yes, let’s call it that). I created an application page in Layouts mapped folder, that reads some POST parameters (id) and outputs either True (if item is of required content type and user has edit permissions for that item) or false otherwise. Then I use jQuery to ‘call’ that application page with $.post and depending on the result I can enable or disable the button.

I use this code for canHandleCommand. Useful trick to first do some asynchronous action before deciding whether to enable the button or not I picked up here.

canHandleCommand: function (commandId) {
    switch (commandId) {
        case 'DoSomething_Command':
            var ids = SomeNamespace.UI.SomePageComponent.getSelectedIds(); // gets array of 'id' of selected items

            var selectionChanged = false;
            if (ids.length != this.previousIds.length) {
                selectionChanged = true;
            } else {
                for (var index in ids) {
                    if (ids[index] != this.previousIds[index]) {
                        selectionChanged = true;
                    }
                }
            }

            if (selectionChanged) {
                this.enabledStatusChecked = false;
            }

            this.previousIds = ids;

            if (!this.enabledStatusChecked) {
                this.checkIsEnabled(ids);
            }

            return this.isEnabled;
    }

    return false;
},
checkIsEnabled: function (ids) {
    this.enabledStatusChecked = true;
    this.isEnabled = false;

    if (ids.length != 1) {
        return;
    }

    var id = ids[0];

    var context = SP.ClientContext.get_current();
    var webUrl = context.get_url();
    var component = this;

    $.post(webUrl + "/_layouts/<Your folder>/_service.aspx", { method: 'hasEditPermission', data: id }, function (data) {
        if (data == "True") {
            component.isEnabled = true;
        }

        RefreshCommandUI();
    });
},

You can see I make sure that selection hasn’t changed and also whether the checking method already ran or not, and then start the method that does the remote call. I do this because once the remote call is finished, I’m calling RefreshCommandUI() function that invokes canHandleCommand again.

Now the remote page is actually pretty simple.

public partial class _Service : LayoutsPageBase
{
    private const string MethodParameter = "method";
    private const string DataParameter = "data";

    protected void Page_Load(object sender, EventArgs e)
    {
        if(Request.RequestType != "POST")
        {
            var web = SPContext.Current.Web;
            Response.Redirect(web.Url);
            return;
        }

        var method = Request.Form[MethodParameter];
        var data = Request.Form[DataParameter];
        Response.Clear();

        switch (method)
        {
            case "hasEditPermission":
                CheckEditPermission(Convert.ToInt32(data));
                break;
        }

        Response.End();
    }

    private void CheckEditPermission(int id)
    {
        var web = SPContext.Current.Web;
        var list = web.Lists.GetList("<Your list id>", false); // or however else you get your list
        var item = list.GetItemById(id);

        if(item.ContentType.Parent.Id != "<Your content type id>")
        {
            Response.Write(false);
            return;
        }

        if(item.DoesUserHavePermissions(SPBasePermissions.EditListItems))
        {
            Response.Write(true);
            return;
        }

        Response.Write(false);
    }
}

I have the switch there in case I wanted to add some more remote methods.

This may not be the most elegant solution ever, but when it comes to sharepoint, you take whatever works. I try not to use complete nonsense or bad practice stuff, but sometimes there are just no good ways to implement something in sharepoint (or all the good ways don’t work ;)).

View comments (0)

Using application page as script service in SharePoint 2010

Posted on Jul 8, 2011

This is sort of a follow-up to my last post. There are few ways to call server methods from javascript other than the one I used. You could also use web services, page methods, http handlers and maybe something else. For something as simple as I was trying to achieve, I didn’t want to go through the bother of setting that up.

Here’s why: web service, either “good” old .asmx or WCF, both require some setting up. Check how to create WCF service here… that’s a lot of steps not to mention you also have to care about how to deploy it to SharePoint. Here is an example of setting .asmx up – and you have to take additional steps if you want to easily call it from javascript.

I couldn’t get page methods to work (EnablePageMethods=”false” in v4.master doesn’t help with the matter), and http handler requires a change to web config. After some considerations, I decided against all of those things, since they are just too complicated for one simple web method, and could be unreliable (we all know SharePoint likes to deploy things wrong all the time).

So I wanted something simple, something I could relate to from MVC, where you can use action method as a web method directly and where are built in methods to return html, string or json. My last post contains my first try at something like that. Since then I refactored it a bit, and moved the core functionality to a base class.

public abstract class ScriptServicePageBase : LayoutsPageBase
{
    private const string MethodParameter = "method";

    protected void Page_Load(object sender, EventArgs e)
    {
        var methodName = Request.Params[MethodParameter];

        var method = GetType().GetMethod(methodName);
        var parameters = method.GetParameters().Select(pn => Request.Params[pn.Name]).ToArray();
        var result = method.Invoke(this, parameters);

        Response.Clear();
        Response.Write(result);
        Response.End();
    }
}

This is just a simple example without any checks, and parameters has to be strings. That could be fixed and extended with some kind of model binder implementation. Just bear with me for now.

Here is a sample script service (code-behind):

public partial class _service : ScriptServicePageBase
{
    public string GetTime(string format)
    {
        return DateTime.Now.ToString(format);
    }
}

And how you call it from javascript with jQuery:

$.post('_layouts/YourProject/_service.aspx', { method: 'GetTime', format: 'dd.MM.yyyy' }, function (data) {
    $('#text').text(data);
});

This is really simple to setup and use, compared to the other options. So I ask, is it really worth it going to all the trouble just to check some permissions or get data for a drop down list? Is there a better solution for this problem in SharePoint? If there is, let me know in comments, otherwise I’m just going to extend this solution, maybe add a method for json conversion and a model binder for parameters, and be happy with that.

View comments (1)

A take on generic RssResult for MVC

Posted on May 8, 2011

When I first needed to support RSS in a MVC web application, it was around the time of MIX 2010. There was a talk by Scott Hanselman, where he explained how to create RSS feed by using a class derived from FileResult. I used it a few times since, but had to always copy+paste it into my new project, and rewrite it to fit my model. So naturally I thought if there was a way to generalize it, and make it reusable across applications. Lately I got into a habit of using Func<> delegates a lot. This is what I came up with:

public class RssResult<T> : FileResult
{
    public IEnumerable<T> Items { get; set; }
    public string Title { get; set; }
    public string Description { get; set; }

    public Func<T, string> GetItemTitle { get; set; }
    public Func<T, UrlHelper, string> GetItemUrl { get; set; }
    public Func<T, UrlHelper, string> GetItemContent { get; set; }
    public Func<T, UrlHelper, string> GetItemSummary { get; set; }
    public Func<T, DateTime> GetItemPusblished { get; set; }
    public Func<T, DateTime> GetItemUpdated { get; set; }

    private RequestContext _requestContext;

    protected RssResult() : base("application/rss+xml") { }

    public RssResult(IEnumerable<T> items, string title, string description, Func<T, string> getItemTitle,
                            Func<T, UrlHelper, string> getItemUrl, Func<T, UrlHelper, string> getItemContent,
                            Func<T, DateTime> getItemPublished, Func<T, UrlHelper, string> getItemSummary = null,
                            Func<T, DateTime> getItemUpdated = null)
        : this()
    {
        Items = items;
        Title = title;
        Description = description;

        GetItemTitle = getItemTitle;
        GetItemUrl = getItemUrl;
        GetItemContent = getItemContent;
        GetItemPusblished = getItemPublished;
        GetItemSummary = getItemSummary ?? getItemContent;
        GetItemUpdated = getItemUpdated ?? getItemPublished;
    }

    public override void ExecuteResult(ControllerContext context)
    {
        _requestContext = context.RequestContext;
        base.ExecuteResult(context);
    }

    protected override void WriteFile(HttpResponseBase response)
    {
        var url = new UrlHelper(_requestContext);
        var items = from item in Items
                    select new SyndicationItem(title: GetItemTitle(item),
                                               content: GetItemContent(item, url),
                                               itemAlternateLink: new Uri(GetItemUrl(item, url)),
                                               id: GetItemUrl(item, url),
                                               lastUpdatedTime: GetItemUpdated(item))
                    {
                        PublishDate = GetItemPusblished(item),
                        Summary = new TextSyndicationContent(GetItemSummary(item, url), TextSyndicationContentKind.XHtml)
                    };


        var feed = new SyndicationFeed(
            Title,
            Description,
            _requestContext.HttpContext.Request.Url,
            items);

        var formatter = new Rss20FeedFormatter(feed);

        using (var writer = XmlWriter.Create(response.Output))
        {
            formatter.WriteTo(writer);
        }
    }
}

Most of this is pretty straight-forward – we have a collection of models, feed title and description, and some delegates to dig information needed for each feed item from a model item. I also pass in an instance of UrlHelper for url, content and summary, because I often generate urls in these fields. Once you have this set up, you can easily create multiple RSS feeds in multiple web applications using this class directly or deriving from it.

Direct approach:

public ActionResult Rss()
{
    var people = _personRepository.GetList();
    return new RssResult<Person>(people, "People list", "A list of people",
                                    p => string.Format("{0} {1}", p.Name, p.Surname),
                                    (p, u) => u.Action("Details", "People", new {id = p.Id}, "http"),
                                    (p, u) => string.Format("This is a description of {0} {1}", p.Name, p.Surname),
                                    p => p.DateCreated);
}

This is a little messy, but gets the job done. A neater solution is to derive from RssResult<T>. You are back to a class per feed scenario, but it’s a lot simpler.

public class PeopleRssResult : RssResult<Person>
{
    public PeopleRssResult(IEnumerable<Person> people, string title, string description)
    {
        Items = people;
        Title = title;
        Description = description;

        GetItemContent = GetItemSummary = (p, u) => string.Format("This is a description of {0} {1}", p.Name, p.Surname);
        GetItemTitle = p => string.Format("{0} {1}", p.Name, p.Surname);
        GetItemUrl = (p, u) => u.Action("Details", "People", new { id = p.Id }, "http");
        GetItemPusblished = GetItemUpdated = p => p.DateCreated;
    }
}
public ActionResult Rss()
{
    var people = _personRepository.GetList();
    return new PeopleRssResult(people, "People list", "A list of people");
}

Another possible refactoring is to extend your controller base class with methods that return your RssResult, and then just say something like return Rss(people); but that has been mentioned about a thousand times already on various blogs, so I’m not going to repeat that.

This class only supports simple feeds, but can serve as a baseline if you need to add some custom stuff as well. Also it should be fairly simple to unit test, since you can just test a bunch of Func<> delegates a check their return value. I will be including this in the next version of NecroNetToolkit which you can now get as a NuGet package.

View comments (0)

Updates to NecroNetToolkit

Posted on Apr 19, 2011

I’m updating NecroNetToolkit at the moment, mainly because of the release of Entity Framework 4.1, so I wanted to write about the changes and show you some things that are now possible. The main update concerns the repository base classes, as I needed to add support for Entity Framework Code First.

That proved a little harder that I initially thought, because the .emdx model classes use ObjectContext, and therefore each set is represented by IObjectSet<TEntity>, but code first uses new wrapper class called DbContext in which sets are represented by IDbSet<TEntity>. These are not compatible, in fact they even have different method naming (Add – AddObject, Remove – DeleteObject).

After some consideration I came up with an adapter that will be used by the repository to communicate with the data store. I’m talking about the repository at the top of the inheritance tree. It will have no clue about what data store is used. In previous version, it used IObjectSet<TEntity> interface to access data, so it was tightly coupled with entity framework – that is no longer the case, this is the reason why I changed the name of the namespace from EntityFramework to Data.

Let’s see some code now, shall we? Here’s the adapter:

public interface IEntityOperator<TEntity> 
{
     void AddEntity(TEntity entity);
     void RemoveEntity(TEntity entity);
     IQueryable<TEntity> GetConfiguredQuery(QueryConfig config);
     IQueryable<TEntity> GetQuery();
}
public abstract class EntityOperatorBase<TEntity, TDataStore> : IEntityOperator<TEntity> 
{
     protected Func<TDataStore> GetStore;

     protected EntityOperatorBase(Func<TDataStore> getStore) 
     {
         GetStore = getStore;
     }

     public abstract void AddEntity(TEntity entity);

     public abstract void RemoveEntity(TEntity entity);

     public abstract IQueryable<TEntity> GetConfiguredQuery(QueryConfig config);

     public abstract IQueryable<TEntity> GetQuery();
}

The methods are pretty straight forward – add, remove, read – configured query is something I have to use Include. The interesting part for me is how I get access to the data store. Remember that instance of this class is a property in the repository, where you also have a property with you DbSet, ObjectSet or whatever you use to store your data. So I’m creating this adapter class in the repository, and passing a delegate that returns a reference to a data store.

You can check out how I implemented these to fit .edmx and code first based repositories on github. But for now, I will show you how to create your own repository based on a different data store. I added this to the toolkit, it’s a in memory repository I thought might be useful for unit testing purposes.

public class MemoryEntityOperator<TEntity> : EntityOperatorBase<TEntity, IList<TEntity>>
{
     public MemoryEntityOperator(Func<IList<TEntity>> getStore) : base(getStore)
     {
     }

     public override void AddEntity(TEntity entity)
     {
         GetStore().Add(entity);
     }

     public override void RemoveEntity(TEntity entity)
     {
         GetStore().Remove(entity);
     }

     public override IQueryable<TEntity> GetConfiguredQuery(QueryConfig config)
     {
         return GetQuery();
     }

     public override IQueryable<TEntity> GetQuery()
     {
         return GetStore().AsQueryable();
     }
}
public class MemoryRepository<TEntity> : UltimateRepositoryBase<TEntity> where TEntity: class
{
     private readonly List<TEntity> _data = new List<TEntity>();

     private IEntityOperator<TEntity> _operator;

     protected override IEntityOperator<TEntity> Operator
     {
         get
         {
             return _operator ?? (_operator = new MemoryEntityOperator<TEntity>(() => _data));
         }
     }

     public override void Clear()
     {
         _data.Clear();
     }
}

With that much code, you get all the capabilities of the repository, with data store of your choice (in this case a in memory list).

View comments (0)

MCTS 70-515 experience

Posted on Apr 18, 2011

I recently got myself a free TS: .NET 4 web applications certification; and since before I did, I didn’t find too much information about what to expect from the exam, what to do before and after, and what to look into, I thought I would share my experiences.

First let me explain how I got it for free. If you are a student, you can get one free Microsoft exam from dreamspark. It’s a fairly complicated process, but there’s a step-by-step tutorial on the site to walk you through it. I was a student until after a week ago, dunno if someone actually checks to see if you really are a student as long as you have valid ISIC card. You can choose from a ton of exams with 72 prefix (these are for students and are cheaper, there is no actual difference in their content). I went with the 70-515 TS: Web Applications Development with Microsoft .NET Framework 4, since that is what I’ve been doing for past two years. You can choose which testing center you want to use (should be several if you live in moderately big city) and also choose the time and date. I chose a date so I had more than a week to prepare for the exam.

So I was signed up, and went online to look for some materials to get ready. One thing I noticed is there are some sites that sell some materials and example test for about $100. I just laughed at that, because as an individual, I’m not about to spend $100 to prepare for $40 exam (if it wasn’t for free). I also tried some free demos of ‘example exam’ software. Most of them were somewhat sketchy, although some questions were in fact similar to the ones on the exam. Not too helpful though.

Other than that, the only content I found were CBT nuggets (snatched from torrent of course, otherwise it’s kind of expensive) and self-paced training kit that costs $40 (I managed to get it from a torrent, but didn’t read it anyway – way too much text). The CBT nuggets videos are worth watching I guess, they only deal with basics, but it’s a nice overview of what to expect. As I said, there was not much to go on. My only preparation was the CBT nuggets and some sketchy looking practice exam software.

Fortunately the exam was easy enough for someone who regularly works with ASP.NET or MVC (or both) that I have been able to pass it. Here’s how is the exam structured: first you answer a few irrelevant questions, and click about a hundred times through various terms and licenses and whatnot before you get to answer the actual questions. Then there are 51 questions that matter. All of these are either multiple or single choice (no drag&drop and similar nonsense), and if it’s multiple choice you know how many choices are correct. I personally like these kinds of tests, since you can usually tell the correct answer by comparing the choices with each other, looking for something that’s wrong with them.

With that, let me tell you what kinds of questions you can expect:

  1. Typical usage of controls such as validators, custom user/web controls, data bound controls – pretty easy stuff
  2. Cache – how to set output cache in and cache dependency in page directive/web.config (VaryByParam, data caching)
  3. When is it correct to do certain things (Init, Load, PreRender etc.)
  4. Localization – remember to always set CurrentUICulture, and know how to user resources in aspx code
  5. Master pages – access master page property from page, set master page type on page
  6. JavaScript – some jquery code to parse xml, selectors, AJAX, DOM manipulation; jquery and standard js – there really was quite a few JavaScript questions, JSON
  7. WCF services – this caught me by surprise – know how to call WCF services from JavaScript, how to setup service host etc.
  8. Web deploy
  9. Little LINQ
  10. Some administration stuff, some was really simple, and some I didn’t know at all so I guessed
  11. MVC 2 – That’s what I work with the most, so that was easiest for me – setup routes, know folder structure, how to add actions and views, areas, html helpers

That’s what I remember anyway. I don’t claim that it is everything there is or could be, but should give you some idea. If you work with ASP.NET and MVC on daily basis, you should have no trouble passing this exam.

I got 790/1000 points if you’re interested. And this is what I have to show for it:

mcts

Tags: ,

View comments (1)

Remote client validation in ASP.NET MVC 2

Posted on Aug 30, 2010

Halfway trough implementing some validation I needed to check on the server by hand in javascript, I realized that xVal (client-side validation framework I used earlier) had something called remote validation rules. I googled around a bit for a solution I could use with built-in MVC validation and found this article from Brad Wilson implementing exactly that. I went trough the comments and it turns out that there is a RemoteAttribute class in Mvc Futures assembly (Microsoft.Web.Mvc.AspNet4 to be exact). It surprised me a little that there was no adapter for this attribute, but fortunately it’s simple enough to write it.

public class RemoteAttributeAdapter : DataAnnotations4ModelValidator<RemoteAttribute>
{
    public RemoteAttributeAdapter(ModelMetadata metadata,
                                  ControllerContext context,
                                  RemoteAttribute attribute) :
        base(metadata, context, attribute) { }
}

Then you need to hook it up at application start:

DataAnnotationsModelValidatorProvider.RegisterAdapter(typeof (RemoteAttribute), typeof (RemoteAttributeAdapter));

I’m good with that. What I didn’t like though, is the client javascript bit. Although it validates the field and displays error message, it doesn’t stop the form from being submitted if there is an error.

Original code (in Mvc futures file MicrosoftMvcRemoteValidation.js):

Sys.Mvc.ValidatorRegistry.validators.remote = function(rule) {
    var url = rule.ValidationParameters.url;
    var parameterName = rule.ValidationParameters.parameterName;
    var message = rule.ErrorMessage;
 
    return function(value, context) {
        if (!value || !value.length) {
            return true;
        }
 
        if (context.eventName != 'blur') {
            return true;
        }
 
        var newUrl = ((url.indexOf('?') < 0) ? (url + '?') : (url + '&'))
                     + encodeURIComponent(parameterName) + '=' + encodeURIComponent(value);
 
        var completedCallback = function(executor) {
            if (executor.get_statusCode() != 200) {
                return;
            }
 
            var responseData = executor.get_responseData();
            if (responseData != 'true') {
                var newMessage = (responseData == 'false' ? message : responseData);
                context.fieldContext.addError(newMessage);
            }
        };
 
        var r = new Sys.Net.WebRequest();
        r.set_url(newUrl);
        r.set_httpVerb('GET');
        r.add_completed(completedCallback);
        r.invoke();
        return true;
    };
};

My version (using jquery):

Sys.Mvc.ValidatorRegistry.validators.remote = function (rule) {
    var url = rule.ValidationParameters.url;
    var parameterName = rule.ValidationParameters.parameterName;
    var message = rule.ErrorMessage;

    return function (value, context) {
        if (!value || !value.length) {
            return true;
        }

        if (context.eventName != 'blur' && context.eventName != 'submit') {
            return true;
        }

        var newUrl = ((url.indexOf('?') < 0) ? (url + '?') : (url + '&'))
                     + encodeURIComponent(parameterName) + '=' + encodeURIComponent(value);

        var valid = false;

        $.ajax({
            url: newUrl,
            async: false,
            success: function (data) {
                if (data != 'True') {
                    valid = false;
                    var newMessage = (data == 'False' ? message : data);
                    context.fieldContext.addError(newMessage);
                }
                else {
                    valid = true;
                }
            },
        });

        return valid;
    };
};

View comments (0)

The time to upgrade your PC is now

Posted on Aug 13, 2010

The SSD drive technology, processors with 4 cores with hyperthreading (now becoming 6 core), DDR 3 memory sticks, powerful graphic cards. If you’ve been waiting to upgrade you PC for a few years, there’s now time like today to start thinking about it. For a developer, having powerful machine is essential for him to be more efficient, faster, more effective, less stressed…. and the list goes on. Take a simple example – when I opened a project in Visual Studio 2010 on my old PC, I could go get something to drink, and when I came back it still wouldn’t be loaded (ok maybe I’m exaggerating a bit, but it took some 15 to 30 seconds for a small project). With my new PC I will be describing later on, the same project takes about 5 seconds to load.

I was displeased with my old PC for a while, so I decided (with a little kick from this post from Scott Hanselman) to build a new one. I would like to walk you through what I bought and did to make the new PC happen, and how it turned out. First, let’s start with a summary of what I had:

start

I had a pretty good graphic card, that’s because the one I had burned out about a half a year ago so I had to buy a new one. I also had a decent power supply (guess what, it also burned out). But the rest of the system was no good. Although 3 years ago, when I bought it, I wasn’t bad – I always buy stuff that is just a bit under the high end, that was true then, and also when I bought my new graphic card. The processor scored lowest (who the hell uses only 2 core processors nowadays?), 4GB (actually my system used only 3 for some reason) DDR2 memory also no good, and a slow disk to top it off.

Before I started the search for parts, I established a few goals for what I want inside my new PC:

  • 4 core processor (1366 socket, so I can change to 6 cores)
  • 12 gigs of ram
  • SSD HDD for system files, 3,5" HDD for data

With that in mind, using before mentioned post from Scott Hanselman as an inspiration, I begun my search.

The processor

By simply applying some facts about processors, I was able to easily narrow it down to a few models. I always liked Intel better, 4 cores, 1366 socket, find a price range that’s comfortable and I’m done. Applying this left me with two models: core i7-930 and an older 920 model that apparently isn’t manufactured anymore.

Price estimate: 6000 CZK (~$300)

The motherboard

Now that I had my processor picked out, I had to find a suitable motherboard that supports LGA 1366 socket, and also has USB 3 and other latest techs. I liked the one Scott suggested, either UD5 or UD7 models.

Price estimate: 5800 CZK  (~$300) for UD5, 6700 CZK  (~$350) for UD7

RAM

I really, really like the ones Scott got, but unfortunately I wasn’t able to get these on a short notice. So instead I got some Kingston with the same parameters (3x4 GB, 1333 MHz, CL9).

Price estimate: 10000 CZK (~$525) – these are expensive as hell in our country :(

HDD

SSD is really the highlight of the whole upgrade. It runs fast, which is good for Visual Studio (I hear it spends most of it’s time on disk I/O operations) and it quiet. Like really quiet, it doesn’t make any noise at all. Well of course, it’s basically a big flash memory, but not hearing the constant rustling noise of standard hard drive is a bliss. I felt comfortable with the 160 GB one that Intel makes. For random data (like movies, TV shows, etc. I’ll keep my 300 GB standard SATA drive).

Price estimate: 9400 CZK  (~$500)

GPU

My GTX 285 that I already have.

Price estimate: 0

So if I sum this up, I end up with about 32000 CZK (~$1700). That’s not counting the value added tax. I was able to buy this through my mothers company for 28000 CZK (~$1500), and using untaxed money to buy this, I got another 25% off, leaving the price at 21000 CZK (~$1100). I admit, I wouldn’t want to buy it in a standard store, because I would have to pay almost twice as much. I assume though that most of you (developers) have a similar way of buying hardware.

The construction

Since this was the first time I was building the PC myself, I carefully followed the motherboard manual to connect everything to the right places. Connecting front panel was a bit of a nightmare, and the power led didn’t work afterwards, but overall I successfully connected everything right. I started the PC, installed fresh copy of windows to my SSD drive, installed some basic programs using this cool site: http://ninite.com/, and setup my CPU meter widget. I noticed that there’s a new feature in that widget that displays CPU core temperatures. The moment I did that it stopped being fun. My CPU was running at almost 60 °C while idle. And when I tried to install Visual Studio, it reached over a hundred degrees. That’s not something I wanted to see, so I immediately canceled the installation, a turned off 2 cores in BIOS.

The temperature wasn’t as high as with 4 cores, but still quite high, and I really didn’t want to have a 4 core processor running only 2 cores. So the next day, I went to the nearest computer shop, and bought Cooler Master Hyper 212 plus and Artic Silver 5. I went trough all the fun of removing the motherboard and inserting it back again. Moreover I also had to clean the CPU (remove the old thermal paste), apply new one, mount the cooler (that is a lot more complicated then installing the stock one, it has a back piece – reason why I had to remove the motherboard).

The results were quite satisfying. CPU was now idling at about 40 °C, but it went to 50 after a while. Day after that I noticed the case was warming up on front side (i mean on the side but in front ;)). I tried to remove the side panel, and few moments later, CPU temperature was back at 40 °C when idle.

Of course I didn’t like the idea of having the case open all the time, so I started looking for a new case. I was considering Antec Nine Hundred, until I saw his big brother Antec Twelve Hundred. This beast weights 14 kilograms, but since I don’t move my PC very often, that doesn’t really matter to me, and I figured 6 fans will cool better than 4.

Naturally I had to remove all the hardware from my old case, and install it into the new one. Let me tell you that was some hard work. You can route cables behind the panel that holds motherboard in place – I took me a while to figure out how to do that right, and also to find out, the some cable just won’t fit there, or aren’t long enough. I managed to put it together after some 3 or 4 hours.

A few thing I like about this case that I discovered after it was delivered: cleanable air filters on intake fans, easily removable hard drive cages through front (though screwed in with 8 screws ;)). I was also surprised by the lighting, which I didn’t care about at all at the time I was ordering it, but it actually looks quite nice.

 

 newpc

 

Recap

A final list of hardware I have now:

My WEI looks a lot better now, mission accomplished.

end 

Next mission: pick up all the leftover hardware, and tune up my server.

View comments (0)