Sitecore8-Examples: ServicesClient Release

Simple post, but I just wanted to let everyone know I’ve posted a new project to the Sitecore8-Examples repository on GitHub. This outlines example usages of the ServicesClient (new to Sitecore 7.5), including basic CRUD operations as well as how to create a service of your own.

If you haven’t heard of this API before, I strongly suggest taking a look. It’s a REST-based API built on the ASP WebAPI includes upgrades to security, build in abstract classes (for making it easier to implement your own services) as well as a supporting JavaScript library (out of the box).

As always, if you have any questions, comments or concerns please use the comments form. If you see any problems, please report them as an issue on the repository. And, finally, if you think you can improve upon what’s there I am accepting pull requests.

flattr this!

Read More

Developing in Sitecore 7.5 — Adding Sitecore Rocks

As part of my Developing in Sitecore series, this post is going to review how to get Sitecore Rocks connected to your Sitecore instance (and then how to add that reference to your project).

NOTE: If you are going to be developing on a local Sitecore instance you will want to run your Visual Studio as an administrator (elevated permissions). This is because when you’re creating the connection, Sitecore Rocks will attempt to publish a helper service (Hard Rock Web Service). This is completely optional, but when developing local (and you have the ability to do so) I recommend using the custom data provider (for reasons explained in the previously referenced link).

Prerequisites:

Establishing a Connection

To begin, we need to establish a connection to our instance. So, from the Sitecore menu in visual studio, select New Connection.

11-1-2014 6-15-36 PM

On the following screen, select your data provider (as mentioned before, I recommend the Hard Rock Web Service), specify the hostname of your instance (I’ll be reusing sitecore75 as I have throughout) and the path to your installation.

11-1-2014 6-16-13 PM

NOTE: If you don’t have direct access to the folder (or don’t care about the upgraded data provider) you can exempt the location. This also means you can ignore the two checkboxes at the bottom.

It’s a good idea to test your connection before accepting, but once you’re confident you have the correct details click OK. You should now see it show up in your Sitecore Explorer looking something like the following:

11-1-2014 6-24-06 PM

Connecting your Project

Now that we have a connection, it’s time to tie that connection with our solution. This is a very simple step and only involves right-clicking on your project and choosing Connect to Sitecore from the Sitecore context menu item.

11-7-2014 10-19-05 AM

In the dialog, select the connection you want to associate.

11-7-2014 10-21-21 AM

That’s it, you’re now connected. If you wanted to confirm your new connection, simply enable ‘Show all Files’ in your solution explorer and look for a new .sitecore file named after your project.

11-7-2014 10-25-55 AM

This file contains the information necessary for Sitecore Rocks to re-connect to your Sitecore instance.

NOTE: It’s up to you if you wanted to check this file into source control, but I tend to ignore it. Because it has no relevance on the project itself, I consider this similar to a .csproj.user file in that it is more for the local developer. (I’ve named my Sitecore instance Sitecore75, but another developer may have called it sc75r140806–for that reason alone I tend to let developers configure their setups independently.) Having said that, this means that anyone pulling the project down would need to establish this connection locally as a first step.

flattr this!

Read More

Developing in Sitecore 7.5 — Solution Setup

In a previous post, I went over the steps required to setup Sitecore 7.5 (including installation of Sitecore itself and MongoDB for analytics). In this post, I will describe the steps involved in setting up a Visual Studio solution so you can begin working with your new installation.

Prerequisites:

First thing’s first, let’s setup our new web project. To do so, open your Visual Studio and create a new ASP.NET Web Application. I’ve named mine “Sitecore75.Web” and changed my solution name to simply “Sitecore75″.

NOTE: Previous practices stated this should be created in the web root alongside your Sitecore instance; That has since changed. It’s now a better practice to keep your project and Sitecore installation separated, for multiple reasons:

  • Separation of what’s live and what isn’t
    By keeping the source code in a different directly, at the end of the day we’re only publishing what’s necessary.
  • Easier source control tracking
    You only need to check in what you’ve created and not the dozens of assets Sitecore itself provides.
  • Re-hydrating made easier
    As you get into bigger projects, you’ll want an easy way to destroy a copy of sitecore and bring it back (think version upgrade, rolling out a new server or continuous integration)

11-1-2014 5-05-12 PM

Next you’ll be prompted for the project defaults. To keep things simple, let’s start off with an Empty web project, and no specific ASP technologies selected (such as Web forms, MVC or Web API).

NOTE: You can chose to include a unit test project at this point, but this is up to you. I find it a bit easier to do so through the project wizard, but that’s entirely up to you.

11-1-2014 5-10-01 PM

Once your new solution has been created, there a few things we need to do immediately. First, remove your web.config transform files for build configurations. These would include the web.release.config and web.debug.config files.

11-1-2014 5-10-46 PM

Next, go to the properties of your web.config and set the Build Action to None.

11-1-2014 5-11-56 PM

This is because we only need it while developing in Visual Studio (for things like scaffolding settings), but do not need (or want) it published to our Sitecore instance. Sitecore already comes with a web.config (with a lot of configurations baked in), so this just allows us to use the same project to target multiple Sitecore instances. Picture using this project to target future versions of Sitecore and not worrying about if we have the right Sitecore web.config in the project.

Moving on, we need to bring our Sitecore DLLs into the project. I like to create a folder within my solution named “sitecore”, then reference them from there. So, all I’ve done is opened the solution folder, created a new folder named “sitecore” and copied my Sitecore.Kernel.dll file from my installed instance’s \bin directory into this folder.

NOTE: Include the corresponding .xml file if you enjoy the comments provided with IntelliSense.

11-1-2014 5-12-30 PM

11-1-2014 5-13-33 PM

11-1-2014 5-57-52 PM

NOTE: If you’re looking to use Analytics you probably want to include Sitecore.Analytics.dll (this would also cover the VisitorIdentification tag). If you’re looking to develop in MVC, make sure to include Sitecore.Mvc.dll & Sitecore.Mvc.Analytics.

After we have the files squared away we’ll want to add them as a reference to our project. So, right click your References of your project and Add Reference. Chose browse, locate your copied dll(s), then include it in your project. (Make sure to repeat this process for your Tests project if you did create one).

11-1-2014 6-01-14 PM

11-1-2014 6-03-15 PM

11-1-2014 6-03-33 PM

Next, set the Copy Local property of the Sitecore dll(s) to false. We’re only including it in our project for reference’s sake (same reason we didn’t need the original Sitecore web.config).

11-1-2014 6-05-52 PM

To get the files to our Sitecore instance, let’s setup publishing. If you’re unfamiliar with this, I recommend reading up on One-Click Publishing. If you are familiar, or if you’re developing local like I am, feel free to follow along with my process:

11-1-2014 6-43-37 PM

11-1-2014 6-43-58 PM

11-1-2014 6-52-07 PM

11-1-2014 6-52-59 PM

11-1-2014 6-54-27 PM

11-1-2014 6-54-02 PM

That’s it. You’re now ready to begin developing (including creating layouts, renderings, etc.) and publishing to your Sitecore instance.

Interested in downloading this solution? Check out the GitHub project (this blog corresponds to release v1.0).

flattr this!

Read More

Developing in Sitecore 7.5 — Setup and Installation

In this post I’m going to attempt to outline how to setup Sitecore 7.5 for use in your development environment. I would like to make it clear this is a practical example, but may not follow best practices or Sitecore’s point of view. Also, things may be brief, but this is a development environment after all, so we don’t need to worry too much about optimizations and splitting up server roles.

To preface the directions, Sitecore 7.5 was released this month and can be found on the Sitecore Developer Network. It comes with some new features, but the significant change is the overhaul to the analytics and the introduction of MongoDB. For more information on the changes, please see the Sitecore 7.5 Release Notes.

To begin the installation, you’ll need the following items:

  • .NET Framework v4.5
    Any version of 4.5.x should work since there’s backwards compatibility. I happen to have 4.5.1 installed currently).
  • MongoDB (at the time of this post, the latest version is 2.6)
    Because this is a developer machine, we can use the free version.
  • Sitecore v7.5 Installer
    I tend to use the executable, but you could use SIM if you’re so inclined.

We start of by installing MongoDB which enables us to record the new analytics information for 7.5. I tend to go the path of least resistance, so the x64 msi was perfect. A few clicks (and some next buttons) and I have MongoDB installed.

The Sitecore installation is next. I find simpler is better for development, so I use the executable and follow all the default installation steps. Shown below, I’ve done a complete install which sets up my IIS website and AppPool for me. You’ll also notice, for simplicity’s sake, I’ve named my instance “sitecore75″.

10-31-2014 2-13-55 PM

10-31-2014 2-14-05 PM

10-31-2014 2-14-12 PM

10-31-2014 2-14-19 PM

10-31-2014 2-14-28 PM

10-31-2014 2-14-59 PM

10-31-2014 2-15-27 PM

10-31-2014 2-15-46 PM

10-31-2014 2-16-03 PM

10-31-2014 2-16-11 PM

On completion, it’s nice to confirm our installation works by checking off “Launch Sitecore”.

10-31-2014 2-17-17 PM

Assuming all went well, You’ll see the wonderful “Welcome to Sitecore” page we all know (and love).

10-31-2014 2-18-25 PM

We still need MongoDB for this instance, so I’ve written a little batch file that gets me going as painlessly as possible. Also, because I bounce between Sitecore instances (and this is only a development environment), I’ve chosen to run MongoDB through a console shell instead of installing at as a service. This is completely up to you on how you want to do it, I just find it easy to run a batch file on-demand rather than a service running all the time.

So, to keep things simple, here is the batch file I use:

Installation is matter of changing the SitecoreInstance setting within the file and saving it off to my instance’s folder to keep things organized (in my case it’s \inetpub\wwwroot\Sitecore75). This also sets up my MongoDB within the \Databases\MongoDB directory, so removing the instance later on is simple and self-contained.

And that’s about it; You should now have a working installation of Sitecore 7.5 running MongoDB locally which can be your open canvas for future websites!

flattr this!

Read More

Using Data-* attributes with Sitecore MVC

If you’ve ever tried to use the data-* attributes in Sitecore you’ve noticed a discrepancy between how Sitecore and the default Html helpers work. Sitecore doesn’t appear to natively support supplying data_* attributes to “parameters” in any of its helpers (I take that back, you can supply them, they just don’t work like you’d expect).

To exemplify, assume you wanted to create a link that perhaps was wired up using KnockoutJS. You may have something like the following:

<a href="/" data-bind="click:SomeAction">Click Me</a>

In MVC, this might looks like the following:

@Html.RouteLink("Click Me", "Sitecore",
    /*routeParameters*/ null,
    /*htmlAttributes*/ new { data_bind = "click:SomeAction" })

In Sitecore, you’d use the Html.Sitecore() helpers. So let’s try mocking the above using the field “Link” (General Link) off our current item:

@Html.Sitecore().Field("Link",
    /*item*/ Sitecore.Context.Item,
    /*parameters*/ new { data_bind = "click:SomeAction" })

The output:

<a href="/">Home</a>

Wait, what just happened?

Sitecore doesn’t understand the data_* attributes like MVC does. MVC realizes that you cannot use keywords/symbols in object names, so it allows you to supplement hyphens with underscores. (Though, if you were really determined to use hyphens, you could also use the IDictionary<string,object> htmlParameters signature overload.)

Sitecore, however, doesn’t understand this (nor does it have a signature overload), so it simply forwards it along as an attribute (exempt of recognized parameters, e.g. “mw” and “mh” when rendering an Image).

The solution? Well, one of the many things I love about Sitecore is even if something doesn’t behave the way you want it to, it’s so customizable that you’re never really stuck. The work-around would be to create a custom process within the renderField pipeline which will allow us to work with these data_* attributes.

First step, create the custom renderField process for the pipeline:

using Sitecore.Diagnostics;
using Sitecore.Pipelines.RenderField;

public class SetDataParameters
{
    public void Process(RenderFieldArgs args)
    {
        Assert.ArgumentNotNull(args, "args");

        // Locate existing "data_* attributes
        var dataAttriubutes = args.Parameters
            .Where(x => String.Compare("data_", 0, x.Key, 0, 5, true) == 0)
            .Select(x => x.Key)
            .ToList();

        // Iterate over them and re-assign them as data-* attributes
        foreach (var originalDataAttribute in dataAttriubutes)
        {
            String reformattedDataAttribute = originalDataAttribute.Replace("_", "-");
            args.Parameters.Add(reformattedDataAttribute, args.Parameters[originalDataAttribute]);
            args.Parameters.Remove(originalDataAttribute);
        }
    }
}

Next, use a config include and register it:

<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/">
  <sitecore>
    <pipelines>
      <renderField>
        <processor patch:before="*" type="MySitecoreProject.Pipelines.RenderField.SetDataParameters, MySitecoreProject" />
      </renderField>
    </pipelines>
  </sitecore>
</configuration>

Now we can continue to supply data_* in the helpers and it will be correctly translated into its hyphenated counterpart. Hope that helps, and if you’ve run into a similar issue leave me a comment.

flattr this!

Read More

Joining Sitecore

Hello everyone!

I’m writing this message as a formal announcement for my decision to join Sitecore. Sitecore is an enterprise Content Management System (CMS) that allows companies to build (and maintain) websites, intranet portals and marketing campaigns through an easy-to-use interface. I’m very exited to begin as I see a lot of potential for both the product and myself within the company.

From here on, I will continue to provide blog posts detailing problems (and solutions) I’ve come across, though from here on in they’ll most likely be regarding the Sitecore platform.

Here’s to a wonderful new venture and a lot of cool future products!

flattr this!

Read More

Mapping with inheritance using KnockoutJS

I just came across an instance where i wanted to map objects using KnockoutJS (and the mapping plugin) to a set of objects I have that use inheritance. I tried several methods, but finally came across one I like and though I would share it.

For instance, say you have DTO objects in a database and you’re using KnockoutJS to show those objects on the page. For argument’s sake, say we have the following:

  1. public abstract class Person
  2. {
  3.     public Int32 Id { get; set; }
  4.     public String Name { get; set; }
  5. }
  6. public class Employee : Person
  7. {
  8.     public String Department { get; set; }
  9. }
  10. public class Customer : Person
  11. {
  12.     public String Company { get; set; }
  13. }

You might change these in to JavaScript objects similar to:

  1. function Person(x){
  2.   this.Id = ko.observable(x.Id);
  3.   this.Name = ko.observable(x.Name);
  4. }
  5. function Employee(x){
  6.   this.Department = ko.observable(x.Department);
  7.  
  8.   Person.call(this, x);
  9. }
  10. Employee.prototype = Object.create(Person.prototype);
  11. function Customer(x){
  12.   this.Company = ko.observable(x.Company);
  13.  
  14.   Person.call(this, x);
  15. }
  16. Customer.prototype = Object.create(Person.prototype);

Okay, but now how do we map it? It’s actually pretty easy. Keep in mind that I use the presence/absence of properties to determine the type to use, but you could just as easily use a discriminator column. Anyways, on with it:

  1. function Person(x){
  2.   this.Id = ko.observable();
  3.   this.Name = ko.observable();
  4.  
  5.   // we add this to make it easier to flag them over to the right. If you had
  6.   // a discriminator column, this wouldn't be necessary.
  7.   this.Type = x.Department ? 'Employee' : x.Company ? 'Customer' : 'Person';
  8.    
  9.   ko.mapping.fromJS(x, {
  10.     include: ['Id', 'Name']
  11.   }, this);
  12. }
  13. function Employee(x){
  14.   this.Department = ko.observable(x.Department);
  15.  
  16.   ko.utils.extend(this, new Person(x));
  17.   ko.mapping.fromJS(x, {
  18.     include: ['Department']
  19.   }, this);
  20. }
  21. function Customer(x){
  22.   this.Company = ko.observable(x.Company);
  23.  
  24.   ko.utils.extend(this, new Person(x));
  25.   ko.mapping.fromJS(x, {
  26.     include: ['Company']
  27.   }, this);
  28. }
  29.  
  30. function App(data){
  31.     this.Persons = ko.observableArray();
  32.    
  33.     ko.mapping.fromJS(data,{
  34.         'Persons': {
  35.             create: function(x){
  36.                 // here we look at which properties exist and
  37.                 // use the appropriate object
  38.                 if (x.data.Department){
  39.                     return new Employee(x.data);
  40.                 } else if (x.data.Company){
  41.                     return new Customer(x.data);
  42.                 } else {
  43.                     // default behavior
  44.                     return new Person(x.data);
  45.                 }
  46.             },
  47.             key: function(x){
  48.                 return x.Id;
  49.             }
  50.         }
  51.     }, this);
  52. }
  53. var d = {
  54.     Persons: [
  55.         { Id: 1, Name: 'Joe', Department: 'Software' },
  56.         { Id: 2, Name: 'Bob', Department: 'Software' },
  57.         { Id: 3, Name: 'Sue', Company: 'WYSIWYG Inc' },
  58.         { Id: 4, Name: 'Bill', Department: 'Accoutns Receivable' },
  59.         { Id: 5, Name: 'Susanne', Company: 'Google' },
  60.         // just to show what a defaulted binding looks like
  61.         { Id: 6, Name: 'Ben' }
  62.     ]
  63. };
  64. ko.applyBindings(new App(d));

Basically, we use ko.utils.extend to bring in the inherited members, then ko.mapping.fromJS to map the properties. Note that only the object itself cares about the properties it has to offer (because the base “class” maps its own).

As I mentioned, you can use a discriminator property to find out which object to map to, but you don’t have to. Just keep in mind it gets a little tricky to decipher which object’s which at the UI level without that property.

Happy coding!

flattr this!

Read More

Dealing with Fractional values

The question Convert a text fraction to a decimal arose and though I’d post a solution to it using a class with the implicit operator. Admittedly I didn’t do a lot of testing on this, but it should handle a great deal of situations as-is. If you need more flexibility, feel free to extend it yourself (and post your modification here so I can update any edge cases).

With that said, here’s the class:

public class FractionalNumber
  1. {
  2.     public Double Result
  3.     {
  4.         get { return this.result; }
  5.         private set { this.result = value; }
  6.     }
  7.     private Double result;
  8.  
  9.     public FractionalNumber(String input)
  10.     {
  11.         this.Result = this.Parse(input);
  12.     }
  13.  
  14.     private Double Parse(String input)
  15.     {
  16.         input = (input ?? String.Empty).Trim();
  17.         if (String.IsNullOrEmpty(input))
  18.         {
  19.             throw new ArgumentNullException("input");
  20.         }
  21.  
  22.         // standard decimal number (e.g. 1.125)
  23.         if (input.IndexOf('.') != -1 || (input.IndexOf(' ') == -1 &amp;&amp; input.IndexOf('/') == -1 &amp;&amp; input.IndexOf('\\') == -1))
  24.         {
  25.             Double result;
  26.             if (Double.TryParse(input, out result))
  27.             {
  28.                 return result;
  29.             }
  30.         }
  31.  
  32.         String[] parts = input.Split(new[] { ' ', '/', '\\' }, StringSplitOptions.RemoveEmptyEntries);
  33.  
  34.         // stand-off fractional (e.g. 7/8)
  35.         if (input.IndexOf(' ') == -1 &amp;&amp; parts.Length == 2)
  36.         {
  37.             Double num, den;
  38.             if (Double.TryParse(parts[0], out num) &amp;&amp; Double.TryParse(parts[1], out den))
  39.             {
  40.                 return num / den;
  41.             }
  42.         }
  43.  
  44.         // Number and fraction (e.g. 2 1/2)
  45.         if (parts.Length == 3)
  46.         {
  47.             Double whole, num, den;
  48.             if (Double.TryParse(parts[0], out whole) &amp;&amp; Double.TryParse(parts[1], out num) &amp;&amp; Double.TryParse(parts[2], out den))
  49.             {
  50.                 return whole + (num / den);
  51.             }
  52.         }
  53.  
  54.         // Bogus / unable to parse
  55.         return Double.NaN;
  56.     }
  57.  
  58.     public override string ToString()
  59.     {
  60.         return this.Result.ToString();
  61.     }
  62.  
  63.     public static implicit operator Double(FractionalNumber number)
  64.     {
  65.         return number.Result;
  66.     }
  67. }

Now your integration should resemble something like:

Double fractional = new FractionalNumber("3 1/2"); // = 3.5

flattr this!

Read More

Suggestive JavaScript save file name using Blob

If you’ve ever wondered how to suggest a file name using JavaScript, I found a method that’s proven to work. Using a Blob, some AJAX and copying an example provided by Google I came up with the following code. I used this successfully within a GreaseMonkey script to be able to automate saving files off, but it should work universally. the only hurdle would be saving files that cross the domain boundary (where GM_xmlhttpRequest can bypass this boundary natively, where as a traditional AJAX request cannot). With that said, here is the code:

  // Here we setup the path to the content (to be retrieved using AJAX)
  var contentUrl  = "/path/to/file.jpg";

  // Helper function that's going to take the data and bundle it in
  // to a blob using whatever Blob method available for the current
  // client's browser
  function dataToBlob(data,mimeString){
    // convert data to ArrayBuffer
    var buffer = new Int8Array(new ArrayBuffer(data.length));
    for (var i = 0; i < data.length; i++){
      buffer[i] = data.charCodeAt(i) & 0xff;
    }

    // http://stackoverflow.com/a/15302872/298053
    try {
      return new Blob([buffer],{type:mimeString});
    } catch (e1) {
      try {
        var BlobBuilder = window.MozBlobBuilder || window.WebKitBlobBuilder || window.BlobBuilder;
        if (e.name == 'TypeError' && window.BlobBuilder){
          bb = new BlobBuilder();
          bb.append([buffer.buffer]);
          return bb.getBlob(mimeString);
        } else if (e.name == 'InvalidStateError'){
          return new Blob([buffer.buffer],{type:mimeString});
        }
      } catch (e2) {
      }
    }
    return null;
  }

  // Perform the actual download (remember that GreaseMonkey can cross domain
  // boundaries. if you find this doesn't work when you port it to an $.ajax
  // call, make sure you're on the same domain (or using JSONP)!
  GM_xmlhttpRequest({
    'method': 'GET',
    'url': contentUrl, // we assign this above
    'overrideMimeType': 'text/plain; charset=x-user-defined',
    'onload': function(response){
      // try to get as much of the metadata from the response as possible. this way
      // all we really need is the contentURL and the rest will come.
      var fileName = response.finalUrl.replace(/^.*[\\\/]/, ''),
          mimeString = response.responseHeaders.match(/^Content-Type: (\w+\/\w+)$/m)[1];

      var blob = dataToBlob(response.responseText, mimeString);
      if (blob){
        // if we were able to process it to a blob, let's create an anchor we can
        // assign the blob to. You can either create a new anchor, or assign it to
        // an existing one. if you do use an existing one, just make sure you set
        // the download, href & dataset.downloadurl properties!
        var a = document.createElement('a');
        a.download = fileName; // or whatever you want to name it
        a.href = (window.webkitURL || window.URL).createObjectURL(blob);
        a.innerHTML = 'Click to save ' + fileName;
        a.dataset.downloadurl = [mimeString, a.download, a.href].join(':');
        a.draggable = true;
        a.style.color = 'white';
        document.body.apendChild(a);
      } else {
        // warn user it's unavailable or do nothing--it's up to you
      }
    }
  });

All of this could just as easily be assigned to a click function (instead of at page load). It’s up to you how you want to implement it.

flattr this!

Read More

Pass HTML to extension method

Lately I’ve been working in MVC a lot and playing around with refactoring page generation approaches to make it more flexible and easier to customize. One method I wanted to pass along was how to pass HTML to a helper (extension) method.

I got the following from (once again) a post over on StackOverflow by Darin Dimitrov and thought I’d post a synopsis here for reference. Let’s say you want to register JavaScript code on your master page/root layout from a DisplayTemplate or EditorTemplate (my purpose was to attach the jQuery tokenInput library to a form in an EditorTemplate). Normally you’d need to bring the code to the top layout and implement it on all pages, but make it only activate when necessary. But below you can take advantage of passing html to a helper (and use the HttpContext to cache the registrations) then output anything registered from any other view. I’ll show you the code:

  1. public static MvcHtmlString RegisterScript(this HtmlHelper htmlHelper, Func<Object, HelperResult> script)
  2. {
  3.   String scriptKey = String.Format("_JavaScript_{0}", Guid.NewGuid());
  4.   htmlHelper.ViewContext.HttpContext.Items.Add(scriptKey, script);
  5.   return MvcHtmlString.Empty;
  6. }
  7. public static MvcHtmlString RenderScripts(this HtmlHelper)
  8. {
  9.   foreach (var key in htmlHelper.ViewContext.HttpContext.Items.Keys)
  10.   {
  11.     if (key.ToString().StartsWith("_JavaScript_"))
  12.     {
  13.       Func<Object, HelperResult> helper = htmlHelper.ViewContext.HttpContext.Items[key] as Func<Object, HelperResult>;
  14.       if (helper != null)
  15.       {
  16.         htmlHelper.ViewContext.Writer.Write(helper(null));
  17.       }
  18.     }
  19.   }
  20. }

And then in a view you’d use something like:

  1. @Html.RegisterScript(
  2.   @<script type="text/javascript">
  3.     $(function(){
  4.       $('#someControl').somePlugin()
  5.     });
  6.   </script>
  7. )

And then back in your _Layout file:

  1. @Html.RenderScripts()

flattr this!

Read More