Tilbake til hovedsiden

WebSeo analyse – Bedrifts Webdesign – IT support – Optimalisering

Finn webside relaterte utrykk og ord

Ajax Extender for Identifying External Links

Author: Fredrik Kalseth

An entry about asp.net | ajax Publication date 4. April 2007 20:46

.NET slave Mads Kristensen wrote a nice post on how to identify external links using JavaScript a few days ago, over on his blog. I had been meaning to implement something similar here, and his post gave me the much needed nudge in the rigth direction – as you can see from the nice little icon next to the link to his post – but this link, which is local, does not have it. Awesome :)

I decided to take the idea a bit further than simply embedding a javascript into my pages, and implemented it as an ASP.NET Ajax ControlExtender instead. The control, which I’ve called ExternalHyperLinkExtender, has the following properties to configure it:

ExternalLinkCssClass
Lets you specify the CSS class that should be applied to external links. Typically, this will be a class that looks something like this:

.ExternalLink 
{
background: url(Icons/ExternalLinkIcon.png) right top no-repeat;
padding-right: 9px;
}

LocalHyperLinkRegex
Lets you specify a regular expression pattern that the extender will then use to identify local links – any link that does not match the pattern will get the ExternalLinkCssClass applied to it. If you do not specify this property, the extender will attempt to determine if the link is external by doing a string compare with the path of the document it is on instead (much like Mads original script does).

AddTargetIfNotSet
If you set this to true, the extender will set the target attribute of the hyperlink to ‘_blank’, if it has not already been set.

A usage example then, would look something like this (taken from the code that renders the very text you are reading now):

<asp:Label
    ID="_text"
    runat="server"
    Text='<%# Eval("Text") %>' />
<iridescence:ExternalHyperLinkExtender
    ID="_textExtender"
    runat="server"
    AddTargetIfNotSet="true"
    LocalHyperLinkRegex="^http://blog\.iridescence\.no"
    ExternalLinkCssClass="ExternalLink"
    TargetControlID="_text" />

I wont go into the details of how to write an ASP.NET Ajax ControlExtender – you’ll find a good walkthrough covering that over at the official ASP.NET site, but below is the javascript code that is the heart of the extender:

initialize : function() 
{
Iridescence.Ajax.ExternalHyperLinkBehavior.callBaseMethod(this, 'initialize');
// get the element we're extending
    var element = this.get_element();
// get all the anchors that are children of the element
    var links = element.getElementsByTagName('a');
for(var index in links)
{
// for each anchor, find any that link off-site
        var link = links[index];     
if(link.href && link.innerHTML && link.innerHTML.length > 0)
{       
var externalLinkFound = false;
if(this._LocalHyperLinkRegex != null && this._LocalHyperLinkRegex.length > 0)
{            
// use regex to test
                var regex = new RegExp(this._LocalHyperLinkRegex);                
externalLinkFound = !link.href.match(regex);                
}
else            
{
// do a simple string comparison to test
                externalLinkFound = !link.href.startsWith(document.location.href.substring(0, 13));
}
// if we found an external link...
            if(externalLinkFound)
{
if(this._AddTargetIfNotSet && !link.target)
{
// ...set target 
                    link.target = '_blank';     
}
if(this._ExternalLinkCssClass)
{
// ...add css class
                    link.className += " " + this._ExternalLinkCssClass;
}
}                                
}
}   
}

Finally, I’ll leave you with this little nugget of sexyness: When all the major browsers (come on, IE team!) gets CSS3 support, we could solve this in a much more elegant way by using the CSS3 Selectors, as described in this post. Now that looks awesome :)

 

Update 17/6 2007

So I finally got around to fixing the bug that prevented this from working in IE6 – basically IE6 always returned ‘undefined’ for link.text, causing my script to skip all links. I’ve changed it to link.innerHTML now :)

Be the first to rate this post

  • Currently 5/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Comments

4/24/2007 7:33:11 AM

Fredrik

Seems to be a bug in my code that prevents this from working in IE7, oops! I’ll get around to fixing it in a few days – or you could just go get Firefox 😉

Fredrik

A Context Menu Control Extender

Author: Fredrik Kalseth

An entry about asp.net | ajax | javascript Publication date 4. August 2007 13:19

One of the things I’ve been missing in the Ajax Control Toolkit, is a context menu extender – so I figured I’d write one myself :) Turns out it was much easier than I anticipated, and after about an hour or so I had something that works fairly well. Basically, it allows you to do something like this:

<asp:Panel
    ID="_context"
    runat="server"
    Style="background-color:#cecece; width:250px; height:250px">            
Context area            
</asp:Panel>
<asp:Panel
    ID="_menu"
    runat="server" 
Style="border:solid 1px black; background-color:White; padding:4px;">
    My Context menu!
</asp:Panel>
<iridescence:ContextMenuExtender
    ID="_cmExt"
    runat="server"
    TargetControlID="_context"
    ContextMenuControlID="_menu" /> 

The extender will then make the TargetControl float wherever the mouse is located when you right-click anywhere inside the configured ContextMenuControl.

You can get the source code at the bottom of this post – below I’ll just go through the javascript code that makes it work. As I said before when talking about control extenders, I will assume that you know how to write them – if you don’t, check out this tutorial for a better introduction than one I could include here :)

To hook things up, we override the initialize function:

initialize : function() 
{
Iridescence.Ajax.ContextMenuBehavior.callBaseMethod(this, 'initialize');
this._contextElement = this.get_element();
this._menuElement = $get(this._contextMenuControlID);
// style the context menu
    this._menuElement.style.display = 'none';
this._menuElement.style.position = 'absolute';
// attach event handlers
    this._onMouseDownHandler = Function.createDelegate(this, this._onMouseDown);
this._onDocumentContextMenuHandler = Function.createDelegate(this, this._onDocumentContextMenu);
this._onDocumentClickHandler = Function.createDelegate(this, this._onDocumentClick);
$addHandler(this._contextElement, 'mousedown', this._onMouseDownHandler);  
$addHandler(document, 'contextmenu', this._onDocumentContextMenuHandler);   
$addHandler(document, 'click', this._onDocumentClickHandler);
}

Here we simply get references to the Target and ContextMenuControls, and then add handlers for the events that we need.

First of all, we need to capture the mousedown event of the context area, so that we may show the context menu when the user right clicks inside it. This is handled by the _onMouseDown method:

_onMouseDown : function(e)    
{                
if (e.button == 2)
{                   
// calculate current mouse position            
        var scrollTop = document.body.scrollTop ? document.body.scrollTop : document.documentElement.scrollTop; 
var scrollLeft = document.body.scrollLeft ? document.body.scrollLeft : document.documentElement.scrollLeft; 
// and move context menu there
        this.__menuElement.style.left = e.clientX + scrollLeft + 'px';
this.__menuElement.style.top = e.clientY + scrollTop + 'px';
this.__menuElement.style.display = '';
// set flags
        this._menuVisible = true;
this._menuJustShown = true;            
}
}

This method checks whether the right mouse button was clicked, and if so we need to figure out the current mouse position (offset by the scroll position), and position the context menu element accordingly, before showing it.

Normally, a right click would cause the browsers context menu to be displayed; we dont want that, as it would hide our custom context menu. Thus we’ve also hooked up to the contextmenu event of the document element, which is handled by the _onDocumentContextMenu method:

_onDocumentContextMenu : function(e)
{        
if(this._menuJustShown)
{
// when our custom context menu is showing, we want to disable the browser context menu
        e.preventDefault();
this._menuJustShown = false;
}
else if(this._menuVisible)
{        
// user right-clicks anywhere while our custom context menu is visible; hide it
        this._hideMenu();
}
}

Here, if our custom context menu was just shown, we prevent the browsers context menu from displaying by calling the preventDefault() method on the event arguments object.

The last functionality we need, is to be able to hide the context menu when the user clicks anwhere outside it after it has been shown. Above, we’ve solved that for when the user right-clicks – we also need to include a left-click solution. We do this by handling the click event of the document element, which is handled by the _onDocumentClick method:

_onDocumentClick : function(e)
{                                   
if(this._menuVisible && e.button != 2)
{
// user left-clicked anywhere while custom context menu is visible; hide it
        this._hideMenu();
}
}

The _hideMenu() function that both these calls is very simple – it just hides the context menu element and sets the _menuVisible flag accordingly:

_hideMenu : function()
{    
this._menuElement.style.display = 'none';
this._menuVisible = false;
}

And thats it! The only thing left is to clean up after us, which we do by overriding the dispose method:

dispose : function()     
{
// clean up
    $removeHandler(this._contextElement, 'mousedown', this._onMouseDownHandler);  
$removeHandler(document, 'contextmenu', this._onDocumentContextMenuHandler);   
$removeHandler(document, 'click', this._onDocumentClickHandler);
Iridescence.Ajax.ContextMenuBehavior.callBaseMethod(this, 'dispose');
}

Now this is a fairly simplistic context menu extender – one might want to add asynchronous loading and maybe animation support at some point – but still, it’s quite impressive how simple the ASP.NET Ajax API makes it to write powerful, reusable components with very little code. Gotta love it :)

Download the complete source code here. (Updated 1. December 2007 – fixed a few bugs in the script).

Update 7. December 2007 –  Be sure to check out this post, which shows how to add animation support to the ContextMenuExtender.

Currently rated 5.0 by 2 people

  • Currently 5/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Comments

8/7/2007 12:12:05 PM

mc

well, for me it worked like a charm! thanks! 😉

maybe you ought to put a small demo projec for the sake of completness.

cheers! 😉

mc

8/20/2007 12:48:07 AM

Jimmy

I got this error

Assembly ‘ContextMenu, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null’ contains a Web resource with name ‘Iridescence.Ajax.ContextMenuBehavior.js’, but does not contain an embedded resource with name ‘Iridescence.Ajax.ContextMenuBehavior.js’.

Jimmy

8/21/2007 8:18:38 AM

Fredrik

Jimmy, you need to set the Build Action on the .js file to ‘Embedded Resource’ in the project (right click and select Properties on the .js file) Smile

Fredrik

10/18/2007 12:56:58 PM

dzhang

I got the same error as Jimmy did and I did set the Build Action on the .js file to ‘Embedded Resource’ in the project, any suggestions?

dzhang

10/19/2007 9:37:36 AM

Fredrik

Hmm, the only other thing I can think of is that you’ve put the code into a different namespace? If so, you need to also change the assembly attribute that registers the embedded resource accordingly.

Fredrik

10/31/2007 10:52:45 AM

Sreekanth

I used this ContextMenuExtender inside GridView in one of my columns. I have a panel that contains two link buttons inside it in the same column of my grid.

Now, when i right click, it is properly showing the context menu, but it is always showing the panel of LAST ROW in my grid. I am not sure what is causing this beahvior.

I even tried to add code to my rowdatabound method that will properly set the ContextMenuControlID to the panel object contained in corresponding Row of the grid. But still it does not work.

If any one thinks that they can help me, please write me a line to my email address given below and i will reply with complete source code.

sreekanthgolla_2000@yahoo.com

Thank you,
Sreekanth.

Sreekanth

11/2/2007 9:49:51 AM

Sreekanth

I fixed the problem i am facing of trying to have more than one ContextMenuExtender in the same aspx page. In my case i have contextmenuextender inside gridview (in one of my columns)

Though i cannot upload the fixed source code here, the solution for the problem is quite simple:

Do not forget to prefix every member variable inside ***Behavior.js file with this. keyword.

If you need the actual fixed ContextMenuExtender.js file, drop me a line of email and i will reply to you.

-Sreekanth.

Sreekanth

11/2/2007 10:44:55 AM

Fredrik

Good catch Sreekanth!

I’ll update the post with the fixes asap Smile

Fredrik

11/9/2007 11:58:39 PM

anikin

Sreekanth, I want your fixed ContextMenuExtender.js file ,thanks

my mail address is anikin2008@hotmail.com

thanks

anikin

12/1/2007 8:14:18 PM

Michael Carr

Thanks for the code, it was exactly what I was looking for.

However, I think I found a small bug.

In your code, you reference “_contextElement” and “_menuElement”. I think you really mean to reference “this._contextElement” and “this._menuElement”. (You reference it correctly in your initialization code, but the rest of the code doesn’t)

The problem doesn’t show up until you try to use several context menus on one page and then funny things start happening.

Thanks again for a great contribution! I don’t know why Microsoft didn’t include an extender like this in the toolbox already…

Michael Carr

12/1/2007 8:25:02 PM

Michael Carr

Oops I guess the bug was already caught above. Next time I’ll read.

Michael Carr

12/2/2007 5:37:33 AM

Fredrik

Thanks Smile
I had actually fixed that bug, but apparently forgotten to update the post&source code download.. should be fixed now!

Fredrik

12/4/2007 1:46:24 PM

IT Hero

Is there a demo project?

IT Hero

12/6/2007 6:18:26 AM

Fredrik

I will be posting an update with some new features and a demo project soon Smile

Fredrik

12/7/2007 5:05:15 AM

aswood

thank you for your code

aswood

12/16/2007 4:56:25 AM

Martin

Hi there,

I have testet your extender and like it ;o)

But is it possible in anyway to add the menu to all the links in a treeview that is populated from a database and then add a ?id=1 to the links in the context menu where the the id is the id beloning to the records from the database ?

Martin

12/18/2007 9:35:43 AM

Thomas

Hi!
Wonderful work, thanks a lot.
I cannot manage this menu to be visible also when I click the left mouse button. How can this be done? I have tried to add e.button == 0 in else clause of method _onMouseDown.

Thanks,
Thomas

Thomas

12/20/2007 4:52:21 PM

Fredrik

Martin – the way the extender is implemented, this won’t be easily possible, sorry. It’s an interesting problem though, I might look into it later – but I can make no promises Smile
Thomas – Have you checked out the PopupControlExtender in the Ajax control toolkit? It can be used to show a popup on a left mouse-button click.

Fredrik

9/29/2008 1:22:04 PM

DuongNguyen

I work well but when i try using two different context menu in a page, but both of them show only the content of the second context menu, how can i fix this bug. Please help me.

DuongNguyen United States

11/10/2008 5:19:33 PM

Jacob Cordingley

Works Great I’m using it for a filter in a gridview
I was able to add a cssContextmenu to style the menu
and set focus where if the menu is a textbox it will focus to it

Jacob Cordingley United States

3/9/2009 3:20:47 PM

Ronald Langi

Hi,

This is great. I need something like this for a gridview. When I click a menu item after right clicking on a row of a gridview to bring up the context menu, how can I pass the key value of that row to the command of the context menu item in java script? I don’t want the page to postback.

Can you help me with this?

Thanks,
Ronald

Ronald Langi Republic of the Philippines

7/10/2009 3:40:08 AM

Maria

Thanks for this great post – I will be sure to check out your blog more often

Maria Republic of the Philippines

7/10/2009 5:01:57 AM

Maria

Nice blog, just bookmarked it for later reference

Maria United Kingdom

Animating an Asp.Net Ajax Control Extender

Author: Fredrik Kalseth

An entry about asp.net | ajax Publication date 7. December 2007 22:14

Earlier this year, I wrote a blog post describing how to develop a context menu control extender using the Asp.Net Ajax control toolkit. It was a fairly basic extender, allowing you to specify a context area and an associated control that should be displayed when the user right-clicked inside that area. In this post I’ll go back and enhance the extender with support for animating the context menu.

What I want to accomplish with the end result, is the ability to write markup similar to the following:

<idc:ContextMenuExtender
    ID="_cme"
    runat="server"
    ContextMenuControlID="_contextMenu"
    TargetControlID="_contextArea">
    <Animations>
        <OnShow>
            <FadeIn Duration="0.25" />
        </OnShow>
        <OnHide>
            <FadeOut Duration="0.25" />
        </OnHide>
    </Animations>
</idc:ContextMenuExtender>

If you’ve used any of the control extenders in the Ajax toolkit like the PopupControlExtender or UpdatePanelAnimationExtender, I’m sure you’ve seen that Animations tag before. It basically allows us to set up one or more storyboards for animations that should trigger on certain events – in the example above, applying a short FadeIn animation when the context menu is shown, and a short FadeOut animation when it is hidden.

The AnimationExtenderControlBase

Originally, my ContextMenuExtender inherited from the ExtenderControlBase class. The first step towards adding support for animations, is changing this to the AnimationExtenderControlBase, which will give me all the leverage I need to easily add animation support to my extender. This new base class has a few members that I’m interested in – there’s the Animations property, and the SetAnimation and GetAnimation methods. As you see from the markup above, the Animations property is the one that we’ll use to set up the storyboard for animations. The cool thing about this, is that it then automatically supports all the pre-built animation types that the toolkit contains – go take a look at the documentation to learn more about animations. The only thing we need to do to make it work, is to set up the different events that we want to support animation – in our case, they’re OnShow and OnHide. We do this by adding similarly named properties on our extender:

[ExtenderControlProperty]
[ClientPropertyName("onShowJson")]
[Browsable(false)]
public Animation OnShow
{
get
    {
return GetAnimation(ref _onShow, "OnShow");
}
set
    {
SetAnimation(ref _onShow, "OnShow", value);
}
}
private Animation _onHide;
[ExtenderControlProperty]
[ClientPropertyName("onHideJson")]
[Browsable(false)]
public Animation OnHide
{
get
    {
return GetAnimation(ref _onHide, "OnHide");
}
set
    {
SetAnimation(ref _onHide, "OnHide", value);
}
}

As you can see, these are decorated with the ExtenderControlProperty attribute to signal that I want the values they get set to, to be transported to the client-side component. Notice also that I’ve used the ClientPropertyName to change the client-side target property – I’m telling the toolkit to map the server-side property OnShow/OnHide to the client-side property onShowJson/onHideJson (or rather, the set_onShowJson/set_onHideJson and get_onShowJson/get_onHideJson methods, as JavaScript has no concept of properties).

That’s it for the server-side changes – the real stuff happens client-side, after all.

Animate Me

Our client-side stuff is defined in the ContextMenuBehavior object. The first thing we do, is to add the client-side properties that we told the server-side component to map the server-side OnShow and OnHide properties to:

get_onShowJson : function() 
{
return this._onShowJson;
},
set_onShowJson : function(value) 
{
this._onShowJson = value;
},
get_onHideJson : function() 
{
return this._onHideJson;
},
set_onHideJson : function(value) 
{
this._onHideJson = value;
}

Now, recall that the Animations property on the server-side extender control was just a string – so our _onShowJson and _onHideJson fields will just end up holding string representations of the animations – incidentally in a JSON format. We can use these strings to create AjaxControlToolkit.Animation objects, and we’ll do that in the initialize method of the component:

initialize : function() 
{
Iridescence.Ajax.ContextMenuBehavior.callBaseMethod(this, 'initialize');
// other stuff removed for brevity...
                
if(this._onShowJson)
{
this._onShowAnim = $AA.buildAnimation(this._onShowJson, this._menuElement);            
}
if(this._onHideJson)
{
this._onHideAnim = $AA.buildAnimation(this._onHideJson, this._menuElement);
}
}

Now, if the any animations were specified, we’ll have them parsed into actual Animation objects ($AA is an alias for AjaxControlToolkit.Animation) in our component, and set to target the context menu (stored in the _menuElement field), ready to be triggered whenever the context menu is shown or hidden. To trigger them, we need to modify the showMenu and hideMenu methods of the ContextMenuBehavior prototype slightly:

showMenu : function(x,y)
{    
// set flags
    this._menuVisible = true;
this._menuJustShown = true;  
this._menuElement.style.left = x + 'px';
this._menuElement.style.top = y + 'px';    
this._menuElement.style.display = '';
if(this._onHideAnim)
{
// if the hide animation is currently running, stop it
        this._onHideAnim.stop();
}
if(this._onShowAnim)
{             
this._onShowAnim.play();
}  
}

Most of this method is the same original – the only difference is that if there’s an OnShow animation specified, we start playing it, first ensuring that any OnHide animation currently playing is stopped.

hideMenu : function()    
{    
if(this._onShowAnim)
{
// if show anim is currently running, stop it
        this._onShowAnim.stop();
}
if(this._onHideAnim)
{
this._onHideAnim.play();
}     
else
    {
this._hideMenuCore();
} 
this._menuVisible = false;
}

The hideMenu method is much the same – if there’s an OnHide animation we start playing it, first ensuring that any OnShow animation currently playing is stopped.

Play With Me

That was a very quick guide to adding support for animations in an Asp.Net Ajax Control Extender. You can read more about using animations over at the Asp.Net Ajax Control Toolkit website.

If you want to play around with the ContextMenuExtender, click here to download a Visual Studio 2008 solution including the source code, and an example project which shows a few usage scenarios of the extender. Feel free to use and abuse it to your hearts content :)

Currently rated 4.0 by 1 people

  • Currently 4/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Comments

10/11/2008 8:13:24 AM

trimurthy

Iam working asp.net 2.0 I have used AnimationExtedet but it should not any onclick events or sequence tags with in animation tag.please replay that quation.

trimurthy India

ASP.NET MVC ActionResult for Rendering JSON using JSON.NET

Author: Fredrik Kalseth
An entry about asp.net mvc | ajax Publication date 1. May 2008 18:03

With the latest drop of the ASP.NET MVC framework, as I’ve mentioned earlier, controller actions now return an ActionResult object. Out of the box, you have the choice between the RenderViewResult, ActionRedirectResult, HttpRedirectResult and EmptyResult types to do different things (they’re fairly self-explanatory, no?). In the application I’m currently working on though, I have several actions which are supposed to only ever get called asynchronously from the client (using jQuery, a totally awesome JavaScript library – more on that some other time), and I want these actions to return a JSON string that can be easily consumed by the JavaScript callback handler. With the help of James Newton-Kings excellent JSON.Net library, all it took to get this working was to implement my own RenderJsonResult class:

/// <summary>
/// An action result that renders the given object using JSON to the response stream.
/// </summary>
public class RenderJsonResult : ActionResult
{
    /// <summary>
    /// The result object to render using JSON.
    /// </summary>
    public object Result { get; set; }
 
    public override void ExecuteResult(ControllerContext context)
    {
        context.HttpContext.Response.ContentType = "application/json";
 
        JsonSerializer serializer = new JsonSerializer();
        serializer.Serialize(context.HttpContext.Response.Output, this.Result);
    }
}

 

My controller actions can then use the anonymous object notation of C# 3.0 to render JSON output:

return new RenderJsonResult { Result = new {status = "ok", assignedId = newItem.Id} };

 

Awesomeness! :)

Currently rated 4.3 by 7 people

  • Currently 4.285714/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Comments

5/1/2008 4:47:52 PM

Kenneth Solberg

Wow, that was really smooth! Will replace my preview 1 View rendering JSON with this way of doing it. Oneliners ftw!

Kenneth Solberg

9/25/2008 5:37:34 AM

Dave

Have you done anything where you are posting back complex types to your controllers?

i.e. suppose you want to post to /Employee/Create and the Create method takes an Employee object…

Thoughts?

Dave

Dave United States

9/25/2008 5:08:43 PM

Fredrik

@Dave, I don’t think it makes much sense to have action methods that take complex objects. I would probably instead have a method like EmployeeController.Create(string name, string address, … Check out my other article on ASP.NET MVC + jQuery and you’ll se an example of this. iridescence.no/…/…h-ASPNET-MVC-and-jQuery.aspx

Fredrik Norway

12/8/2008 5:19:32 AM

Rean

Hi Fred,
In asp.net webforms I used James Newton-King’s Jayrock json serializer to send json objects to server side as .net objects. For e.g. I would send a json object to a JsonRpcHandler method with attribute JsonRpcMethod and it would accept it as an IDictionary. I will than play with it and send back a .net serializable object which would automatically be converted to json by the handler. This way the two way communication is json.
How will I achieve this in asp.net mvc?
Confession: I haven’t explored asp.net mvc a lot.

Rean India

3/16/2009 12:01:51 PM

virus

when i use you code,for example

public class ShiwbController : Controller
{

public ActionResult ShowJson()
{
var json = new User { Name = “author”, Sex = “male” };
return new RenderJsonResult { Result = new { status = “ok”, assignedId =123 } };

}
public ActionResult js()
{
return JavaScript(“var i=0;”);
}
}
public class RenderJsonResult : ActionResult
{
public object Result { set; get; }
public override void ExecuteResult(ControllerContext context)
{
context.HttpContext.Response.ContentType = “applicaion/json”;
Newtonsoft.Json.JsonSerializer serializer = new Newtonsoft.Json.JsonSerializer();
serializer.Serialize(context.HttpContext.Response.Output, this.Result);
}
}

when i visit http://localhost/showjson ,there is a messagebox to let me download file “showjson”,and this is appear when i visit http://localhost/js , why not?
thank you

virus People's Republic of China

Invoking ASP.NET MVC Actions from JavaScript using jQuery

Author: Fredrik Kalseth

An entry about asp.net mvc | ajax | javascript Publication date 31. May 2008 11:27

One of the things that the MVC model is really great at, is integrating with Ajax. I blogged about a RenderJsonResult class a few weeks ago that one could use to create controller actions which render their output as Json – since then the last ASP.NET MVC framework drop also includes a JsonResult type of its own. What I didn’t talk about in the mentioned post, was how to actually invoke such actions from JavaScript; enter jQuery.

Ajax with JQuery

In the crowd of JavaScript libraries out there, JQuery is probably the most unique – at least for now. Its main features are the abilities to query and manipulate the DOM using syntax that anyone familiar with CSS will feel at home with. But jQuery offers more than this – it also has an Ajax API. With this, we can easily perform a POST or GET on a controller action and handle the result it returns asynchronously.

As an example, lets assume we have a FeedbackController with an action Submit:

public ActionResult Submit(string author, string email, string comment)
{
    // logic for submitting feedback omitted
 
    return new RenderJsonResult {Result = new {success = true, message = "Thank you! We value your feedback."}};
}

 

Invoking this from JavaScript using jQuery is super easy:

$.ajax(
{
   type: "POST",
   url: "/Feedback/Submit",
   data:"author=" + author + "&email=" + authorEmail + "&comment=" + comment,
   success: function(result)
    {
        if(result.success) $("#feedback input").attr("value", ""); // clear all the input fields on success
        $("#feedback_status").slideDown(250).text(result.message); // show status message with animation
    },                
   error : function(req, status, error)
   {
        alert("Sorry! We could not receive your feedback at this time.");   
   }
});

 

We set the type of the call to POST, because we need to send some data with our request, which we use the data option to specify. jQuery allows us to provide a few callback methods that will be invoked on the success or failure of the Ajax call. If our call is successful, the success callback gets invoked, which gets passed an object representing the result of the Ajax call. jQuery is able to handle results formatted in different styles, including xml, html, script and json. You can specify the expected data type using the dataType option. Leaving it out will cause jQuery to choose the type based on the MIME type of the response, which is usually fine. There are other options which can be used; you’ll find a complete description of them here. The code in the success callback uses the selectors, attributes, manipulation and effects APIs to reset the input fields and tell the user that the feedback was received.

It’s simple, it’s elegant – and so, so far removed from the bloated UpdatePanels of ASP.NET.

Surface Scratched

This post merely scratches the surface of what is possible when combining ASP.NET MVC with jQuery (or other Ajax APIs for that matter). Look out for more posts on this topic in the future!

Currently rated 4.2 by 20 people

  • Currently 4.2/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Comments

8/5/2008 4:21:16 AM

Michael Hart

Simpler:

return Json(new {success = true, message = “Thank you! We value your feedback.”});

Michael Hart Australia

8/5/2008 10:45:22 AM

Fredrik

@Michael: Yeah, you’re right – but this post was written using the preview 2 of the ASP.NET MVC framework; they didn’t add the Json() methods until later Smile

Also note that the Json() methods in preview 4 uses the JavaScriptSerializer class internally; my approach uses the JSON.NET framework.

Fredrik Norway

12/19/2008 11:23:35 AM

Alexis

Great post – much less “hack-ish” than a lot of the other tutorials out there.

Alexis South Africa

1/27/2009 2:45:24 AM

pingback

Pingback from goneale.wordpress.com

Submitting an AJAX Form with ASP.NET MVC + jQuery « {Programming} & Life

goneale.wordpress.com

4/1/2009 2:47:42 PM

devix

Nice Information……….

devix United States

4/3/2009 10:48:36 PM

Jason

Exactly what I needed. Very helpful.

Jason United States

6/22/2009 3:37:46 AM

Praveen

I believe you need to add the below definitions while doing a jQuery .ajax

contentType: “application/json; charset=utf-8”,
dataType: “json”

I needed the above to make it work, esp. processing the returned result at the
Javascript end.

-Praveen

Praveen Australia

7/10/2009 2:43:46 AM

Paul

Nice blog, just bookmarked it for later reference

Paul Republic of the Philippines

7/10/2009 4:06:13 AM

Paul

BAAAM Nice Post dude! Do more >D

Paul United Kingdom

Partial Rendering with ASP.NET MVC and jQuery

Author: Fredrik Kalseth
An entry about asp.net mvc | ajax | javascript Publication date 1. June 2008 13:57

Yesterday, I wrote a post detailing how easy we can invoke an ASP.NET MVC controller action from JavaScript using jQuery. Lets up the ante a bit, and see if we can’t use the same approach to get some partial rendering going. To accomplish this, we’ll use a fact about the RenderViewResult class that hasn’t got a lot of attention so far – the fact that its View propetry can be set to point at a UserControl, not just a WebForm. When doing so, only the user control will be rendered – which sounds like exactly what we need for doing partial rendering..

Rendering User Controls

Lets say we’re building a simple task list. We might have the following UserControl representing a single task:

<%@ Control Language="C#" AutoEventWireup="true" CodeBehind="Task.ascx.cs" Inherits="MvcApplication2.Views.Tasks.Task" %>
<div class="task">
    <div class="task_name"><%= ViewData.Name %></div>
    <div class="task_due"><%= ViewData.Due %></div>
    <div class="task_desc"><%= ViewData.Description %></div>
</div>

 

Our TaskList view may then use this to render a list of tasks:

<h1>Tasks</h1>
 
<div id="task_list">
    <% foreach(Task task in ViewData) {%>
        <%= Html.RenderUserControl("~/Views/Tasks/Task.ascx", task) %>
    <%} %>
</div>
 
<h1>Add task</h1>
 
Name: <input type="text" id="newtask_name" /><br />
Due: <input type="text" id="newtask_due" /><br />
Description: <input type="text" id="newtask_desc" /><br />
<input type="button" onclick="AddTask()" value="Add" />

 

The TaskList view is rendered by the Index action on our TaskController, which looks like this:

public ActionResult Index()
{
    Task[] tasks = // get tasks from repository
 
    return RenderView("TaskList", tasks);
}

 

Next, we need an action for creating a new task. However, we want to invoke it from JavaScript, and have it only return the markup for the new task item so that we can append it to the task list dynamically, instead of refreshing the entire page. To accomplish this, we implement it using the previously mentioned trick of the RenderViewResult class:

public ActionResult New(string name, string desc, DateTime due)
{
    Task task = new Task { Name = name, Description = desc, Due = due };
    // ...save task to repository
    return RenderView("Task", task);
}

 

Notice here that “Task” points to the Task.ascx user control, not a Web Form. When invoked, this action will render the markup for that control only.

Manipulating the DOM

Like I mentioned in yesterdays post, we can tell jQuery to handle the response from an Ajax call as html. More than that, we can use jQuery to create a DOM element for us from the returned html, and drop it anywhere in our document. The following JavaScript function accomplishes both:

function AddTask()
{
    var name = $("#newtask_name").attr("value");
    var due = $("#newtask_due").attr("value");
    var desc = $("#newtask_desc").attr("value");
 
    $.ajax(
    {
       type: "POST",
       url: "/Tasks/New",
       data: "name=" + name + "&due=" + due + "&desc= "+ desc,
       dataType: "html",
       success: function(result)
       {
            var domElement = $(result); // create element from html
            $("#task_list").append(domElement); // append to end of list        
       }
    });        
}

 

Here, we’re making an Ajax call to the New action on the Tasks controller. We then create a new DOM element from the resulting html that it renders, and append it to the task list. And that’s it! When the user adds a task, the following POST is sent:

Post

The following response is received from the server, which we append to the task list:

Response

If you want to take a look at a working example, you can download the project I used to demo this here.

Note: For some reason, the Ajax calls are quite slow (~1 sec) when running the demo using Visual Studio’s built-in development server. Publish the site to IIS however, and things are blazingly fast (as you can see from the screenshots above) :)

Currently rated 4.6 by 16 people

  • Currently 4.5625/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Comments

6/1/2008 4:03:47 AM

Jonas Follesø

Another great post!

I got sick of doing ASP.NET Web Forms applications back at 1.1/2.0. Didn’t like the abstraction level. With ASP.NET MVC, support for multiple AJAX frameworks, and better browsers with CSS 2.1 support I really want to get back to doing web development again.

The combination of ASP.NET MVC with a touch of Silverlight 2 is going to enable us to build som truely amazing web applications Smile.

My next project is deff. going to involve MVC + JQuery.

Cheers,
Jonas

Jonas Follesø

6/1/2008 10:08:52 AM

Josh

For the slowness of the Ajax… and in FF in general… did you set ‘network.dns.disableIPv6’ equal to true? This speads up FF when a project is in debug mode…

FF in address bar:
about:config

Josh

6/1/2008 10:40:18 AM

Fredrik

@Jonas: Totally agree. Even though I was fairly happy with ASP.NET and what it let me achieve, moving to ASP.NET MVC was very liberating and I’m not looking back. Add to that the fact that JavaScript frameworks are really maturing now (jQuery, Prototype etc), along with great tools (Firebug!), the fun has definitively been injected back into web development Smile

@Josh: Thanks for the tip! It did the trick Smile

Fredrik

6/1/2008 11:56:08 AM

Andy

Good initial sample, though I suppose it would be great to include Add Task in a Form element to allow full postback when javascript is disabled. I’d be then interested in which CancelLayout type approach you would then take to either render the UserControl or a full page. And perhaps use val() rather than attr(‘value’) with jQuery.

Andy

6/3/2008 1:08:29 PM

Fredrik

That’s a good point, Andy. By wrapping the input in a form as you say, you could then make the New action return an ActionRedirectResult instead of a RenderViewResult when the form was posted with javascript disabled, redirecting to the Index action which would then render the full page and not just the added task.

Fredrik

6/15/2008 1:51:32 PM

Rafael

Hi.

I`ve just started to play around with MVC and stumbled in a problem. I`ve used your sample code and it worked as dream with simple user controls, but when I tried to put an ImageButton on it and it ceased to work. The message says:

Control ‘ctl00_ImageButton1’ of type ‘ImageButton’ should be inserted inside a markup with runat=server

I`ve changed all containers to runat=server but it didn’t work. Am I missing something here?

By the way, the RenderView() method was renamed to View() in MVC preview 3?

Thanks a lot,
Rafael.

Rafael

6/19/2008 4:47:28 AM

jhggv

gnvbg

jhggv

6/22/2008 12:23:14 AM

Kevin Ortman

Fredrik, fantastic example… straight to the point. Thank you!

Rafael, MVC doesn’t support the full ASP.NET page lifecycle, thus the server controls are not supported. Instead, you should use the UI Helpers. See blog.wekeroad.com/…/ for an explanation / example.

Regards,
Kevin

Kevin Ortman

8/4/2008 11:24:52 AM

yang

If you developed a real-world application with Asp.net mvc you should already know that developing forms with lots of validation reaalllyyy takes time. Knowing what is happening behind the curtain and having full control on the application is great but take my advice and don’t get into developing form heavy applications yet with mvc. Just wait for some improvements (one came out with preview 4 already, ajax support), especially for validation. (Yes I know we have serious client-side validation frameworks like jquery.validate, but client-side validation is only the half)

yang Turkey

9/18/2008 4:36:55 PM

Sean

Fredrik, thanks for posting this tutorial its helped me out a lot in getting my first MVC app up and running while using jQuery to take care of AJAX calls. I’m still pretty new to jQuery and I’m trying to do something similar to what you have done in your AddTask() function. This is my ajax call:
$.ajax(
{
type: “POST”,
url: “/Product/New”,
data: “name=” + name + “&desc=” + desc + “&stock=”+ stock + “&price=” + price,
dataType: “html”,
success: function(result)
{
var domElement = $(result); // create element from html
if($(“div.new-product”).length > 0){
(domElement).replaceAll(“div.new-product”);
}
else {
$(“#product_list”).append(domElement); // append to end of list
}
}
});

It works except that I am trying to decide where to place the result based on whether or not it contains an element with class “new-product” and it always just appends the result to the #product_list div in my page. I can’t seem to figure out how to search the result html for an element by class. If you have any suggestions I’d appreciate it and again thanks for the great tutorial.

Sean United States

9/18/2008 4:38:41 PM

Sean

Sorry the If block in that previous code was in the process of editing, this is how it actually looks and it still doesn’t work.

if($(“div.new-product”,result).length > 0){
(domElement).replaceAll(“div.new-product”);
}
else {
$(“#product_list”).append(domElement); // append to end of list
}

Sean United States

9/19/2008 3:12:10 PM

Fredrik

At a glance, my guess is that you need to change $(“div.new-product”, result) to $(“div.new-product”, domElement).

Fredrik Norway

9/19/2008 5:01:45 PM

Sean

Thanks Fredrik, I did get it working I had to do the if block like this:
if($(result).filter(“div.new-product”).length > 0){
$(“div.new-product”).replaceWith(domElement);
}
else {
$(“#product_list”).append(domElement);
}

Works perfectly like that.

Sean United States

9/19/2008 5:15:56 PM

Fredrik

Cool Smile

Fredrik Norway

10/3/2008 9:49:47 PM

pingback

Pingback from justanothercoder.com

My RenderControl Anti-Pattern at Just Another Coder

justanothercoder.com

Keeping a Transaction from Escalating

Author: Fredrik Kalseth

An entry about ado.net Publication date 20. December 2007 20:32

With the introduction of the System.Transactions namespace in .Net 2.0, working with transactions became dead easy. All you need to do is wrap the section of code you want to be transacted in a TransactionScope, and the framework will take care of the rest. There’s one problem though – if you open more than one database connection during the scope of the transaction, then the transaction escalates to a two-phase transaction, which means enlisting the help of the the Microsoft Distributed Transaction Coordinator service. Apart from the obvious overhead of communicating with this unmanaged service on your database server, there’s another reason for wanting to avoid this – it might not be running. If you’re hosting your application on a shared web host for instance, chances are their database server will have the MDTC disabled, and chances are they won’t enable it for you either. So what can a poor programmer do then?

He can be clever about reusing the connections when working inside a transaction. This article will show how we can write a custom DbProviderFactory proxy that intercepts any CreateConnection() calls and reuses connections while inside a transaction scope. The beauty of this implementation is that, as long as you’re using the DbProviderFactories (which you really should!) to create your connections, it will be totally transparent to your code. This is important because a transaction might be a high level concept in your code, far removed from the data access layer.

DbProviderFactory, Please

By implementing our data access layer so that it always queries the current DbProviderFactory for a connection, then there is one central place where connections are created, vastly simplifying what we want to do. Imagine then, that we have a DataStore that looks something like this:

public class DataStore
{
private string _connectionString;
private DbProviderFactory _dbProviderFactory;
public static readonly DataStore Instance = new DataStore();
private DataStore()
{
_dbProviderFactory = DbProviderFactories.GetFactory(ConfigurationManager.ConnectionStrings["Iridescence.Data.DataStore"].ProviderName);
_connectionString = ConfigurationManager.ConnectionStrings["Iridescence.Data.DataStore"].ConnectionString;
}
// datastore methods here...
}

This is in fact the constructor from my DataStore API (simplified for clarity), which you can read more about here. Notice how we load up a DbProviderFactory by reading a few configuration settings, and storing them for use later. Our app.config looks like this:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<connectionStrings>
<add name="Iridescence.Data.DataStore" providerName="System.Data.SqlClient" connectionString="..."/>
</connectionStrings>
</configuration>

The providerName attribute tells the DataStore which factory to use – in this case the SqlClient factory, which is the Ado.Net factory for Sql Server. Now, whenever the DataStore needs a connection, all it has to do is call the CreateConnection() method on the factory. Having our DataStore implemented in this way enables us to ensure there is one central place where connections are created – and more importantly, a plugable one which we can substitute the implementation of.

Implementing a Transaction Aware DbProviderFactory

Having this extensibility point in our code, we can then take advantage of it to incorporate connection reuse into the DataStore. All we need to do, is write a custom DbProviderFactory that knows when CreateConnection should create a new connection, and when it should keep returning the same instance several times to reuse an existing connection. Here’s the code we need:

public sealed class DbConnectionScope : DbProviderFactory
{
private readonly DbProviderFactory _realFactory;
private readonly Dictionary<Transaction, DbConnection> _transactionConnections = new Dictionary<Transaction, DbConnection>();
///<summary>
    /// Creates a new instance of the DbConnectionScope class
    ///</summary>
    ///<param name="factoryToScope">The factory to scope</param>
    public DbConnectionScope(DbProviderFactory factoryToScope)
{
_realFactory = factoryToScope;
}
///<summary>
    ///Returns a new instance of the provider's class that implements the <see cref="T:System.Data.Common.DbConnection"></see> class.
    ///</summary>
    ///
    ///<returns>
    ///A new instance of <see cref="T:System.Data.Common.DbConnection"></see>.
    ///</returns>
    ///<filterpriority>2</filterpriority>
    public override DbConnection CreateConnection()
{
Transaction transaction = Transaction.Current;
// we're not currently in a transaction, so we just let the real factory work normally
        if(null == transaction)
{
return _realFactory.CreateConnection();
}
else // we're in a transaction, so we want to ensure connection reuse
        {
DbConnection connection;
if (!_transactionConnections.TryGetValue(transaction, out connection))
{
// this is the first time this transaction requests a connection. 
                // Lets create it, wrapping it in a ScopedConnectionProxy which will 
                // ensure that any call to Close does not result in actually closing the connection 
                // (because we want to reuse the open connection throughout the entire transaction scope)
                connection = new ScopedConnectionProxy(_realFactory.CreateConnection());
_transactionConnections.Add(transaction, connection);
// we need to know when the transaction ends, so we can close the connection.
                transaction.TransactionCompleted += transaction_TransactionCompleted;
}
return connection;
}
}
void transaction_TransactionCompleted(object sender, TransactionEventArgs e)
{
DbConnection connection;
// transaction has ended, remove it from the cache and ensure it is disposed
        if(_transactionConnections.TryGetValue(e.Transaction, out connection))
{
_transactionConnections.Remove(e.Transaction);
connection.Dispose();
}
}
}

We’ve implemented our factory using the transparent proxy pattern, so that it wraps the actual DbProviderFactory and extends it with connection reuse functionality whenever a transaction is present. There is one problem left to tackle however, and that is keeping the connection alive – because most likely, the DataStore will do the following whenever it requests a connection:

using (IDbConnection connection = _dbProviderFactory.CreateConnection()
{
using (IDbCommand command = connection.CreateCommand())
{
// prepare and execute command
    }
}

This is of course a good thing as it ensures we don’t leave any connections lying around – they’re scarce resources, after all – but it causes a problem for our factory; the connection will be closed and disposed, so when we return the same instance the next time, it won’t be very reusable, which kinds of defeats what we were trying to accomplish… Resorting to the transparent proxy pattern again, we can solve this by wrapping the connection returned in a proxy that ensures that any call to Close and Dispose is only effective if the transaction has ended:

private class ScopedConnectionProxy : DbConnection
{
private readonly DbConnection _realConnection;
public ScopedConnectionProxy(DbConnection realConnection)
{
_realConnection = realConnection;
}
/// <summary>
    /// Closes the connection if connection reuse is disabled or we're not currently inside a transaction.
    /// </summary>
    public override void Close()
{
Transaction transaction = Transaction.Current;
if (null == transaction || transaction.TransactionInformation.Status != TransactionStatus.Active)
{
_realConnection.Close();
}
}
protected override void Dispose(bool disposing)
{
Transaction transaction = Transaction.Current;
// only dispose if transaction has ended. Otherwise, 
        //transaction end event will dispose the connection for us
        if (null == transaction || transaction.TransactionInformation.Status != TransactionStatus.Active)
{
_realConnection.Dispose();
base.Dispose(disposing);
}
}
}

And there you have it. The only change needed in our DataStore to active the connection reuse, is to wrap the DbProviderFactory in our proxy:

private DataStore()
{
_dbProviderFactory = DbProviderFactories.GetFactory(ConfigurationManager.ConnectionStrings["Iridescence.Data.DataStore"].ProviderName);
_dbProviderFactory = new DbConnectionScope(_dbProviderFactory);
_connectionString = ConfigurationManager.ConnectionStrings["Iridescence.Data.DataStore"].ConnectionString;
}

Why Transactions Escalate

To end off, I’d like to point out that this solution does not guarantee that the transaction will not escalate. What really happens when you open up a second connection, is that a second entity takes part in the transaction, and this is the reason for the requirement to escalate it. As long as there’s only one entity involved, that entity can take ownership of the transaction and coordinate it, but when more than one entities are involved a distributed transaction coordinator is needed to hold the reins. For the most part when dealing with the kind of transactions discussed here, which relate to updating stuff in the database, the connections are the only entities that will be involved. But its perfectly possible to introduce other entities – for instance you might write your own in-memory object transaction manager by implementing the IEnlistmentNotification interface and enlisting it with the transaction to ensure that a roll-back also reverts the object to keep it in synch with the database. That might be a good post for later :)

Get the Source Code

You can download my DbConnectionScope implementation here. I threw this together in half an hour this evening, so its not really been tested thoroughly. In particular, I’ve not really implemented the DbProviderFactory proxy fully, and only focused on the CreateConnection method. Look out for a follow-up post on this topic later, which will also include the DataStore API update that takes advantage of the proxy.

Oh yes, and in case this is the last post this year, I’d like to wish everyone a merry Christmas and a happy new year! Cheers :)

Currently rated 5.0 by 1 people

  • Currently 5/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Comments

12/31/2007 10:07:52 PM

Mike

I thought this was a SQL 2000 issue? But SQL 2005 handles this ok.

Good article though.

Mike

1/1/2008 12:15:49 AM

Fredrik

To my knowledge, this is a problem with any version of SQL Server. If you start a transaction then open, then close, then open a new connections, it will cause the transaction to escalate. By forcing reuse of the connection, it will make sure the transaction does not escalate in this particular scenario. But I’ve only tested this exhuastively on SQL Server 2005 so far Smile

Fredrik

6/28/2009 1:21:48 PM

trackback

Trackback from Magnetic Body Wrap

Magnetic Body Wrap

Magnetic Body Wrap

7/10/2009 1:22:12 AM

Xavier

Nice blog, just bookmarked it for later reference

Xavier Republic of the Philippines

7/10/2009 2:48:42 AM

Paul

BAAAM Nice Post dude! Do more >D

Paul United Kingdom

7/10/2009 11:26:19 AM

Xavier

Very interesting post – Might be old new, but it was new to me. Thanks. btw. can you checkout my blog to? its http://www.site2money.com/google

Xavier United Kingdom

7/10/2009 11:34:24 AM

solar

awesome info presented. As Arnold said ” i’ll b back”

solar United States

Design by Contract with .NET 4.0

Author: Fredrik Kalseth

An entry about visual studio | .net 4.0 Publication date 6. November 2008 16:33

Justin van Patten has put together a great list of all the new features that will ship with .NET 4.0 – both new features in the BCL, as well as the new features in the C# language itself. One of the additions to the BCL comes from Microsoft Research, and is called Code Contracts.

Code Contracts is a language independent tool which allows you to embed rules about the inputs, outputs and invariants in your code. When this information is embedded in the code, the Code Contract tools can perform both static and runtime analysis of the code to ensure that it is not breaking any of the rules defined. Sounds a lot like Spec#, doesn’t it? Well, Code Contracts is essentially a port of the static and runtime verification concepts from Spec# into an API which will ship as part of the .NET 4.0 Base Class library.

Let´s look at an example: Imagine that we have an API with the following silly method somewhere in it:

public static string GetTypeName(object obj)

{

    if(null == obj) throw new ArgumentNullException(“obj”);

    return obj.GetType().Name;

}

The problem with this, is that there´s no way for a client of this API to know what happens if they pass a null value to this method. Does it crash? Return a null? Return an empty string? By using the Code Contract API, we can make such details of our implementation explicit:

public static string GetTypeName(object obj)

{

    CodeContract.Requires(null != obj);

    return obj.GetType().Name;

}

If someone writes code that calls this method and passes a value that might be null, and we have static checking of code contracts turned on in our project, we will get the following warnings from the compiler:

image

The first warning tells us that the contract we have defined was violated (not very helpful the messages yet, but it is an early beta after all), and the second warning points us at the code that is violating the contract.

In addition to setting up contracts that constrain the inputs to a method, we can also set up contracts that talk about the outputs. for instance, imagine that our original method looked like this instead:

public static string GetTypeName(object obj)

{

    return null != obj ? obj.GetType().Name : “<null>”;

}

This time, our method will happily accept an argument which is null, and it will always return a string. Using code contracts, we can embed this fact into our method:

public static string GetTypeName(object obj)

{

    CodeContract.Ensures(CodeContract.Result<string>() != null);

    return null != obj ? obj.GetType().Name : “<null>”;

}

These examples are just scratching the surface of what is possible. In addition to defining contracts that talk about the entry and exit points of methods, there´s also invariant contracts that deal with the state of the object as a whole. Contracts can also be defined on interfaces. More tools that take advantage of the contracts will also become available – for instance tools that auto-generate documentation, and of course there are great opportunities for integration with PEX here.

If you want to learn more about the features available and how they all actually work under the covers, then check out the recording of the PDC 2008 session by Mike Barnett and Nikolai Tilmann over at Channel9. I really recommend watching it – they do a great job of explaining the concepts (the first part is about Code Contracts, the second about PEX).

You can also go and download a preview of the framework and tools for Visual Studio 2008 over at the Microsoft Research site.

Comments

11/9/2008 7:28:51 PM

Lerxst

Interesting concept. One thing that I like in Java is the syntax

void SomeMethod(object i) throws MyNullArgumentException {…}

..as it makes the expectations of the function more explicit.

But this is just an excuse to make you a silly question: why do you write “null==obj” instead of “obj==null”? Any specific reason, or just a question of style?

Keep up your great blog, lots of good information here.

Lerxst Belgium

11/10/2008 10:26:28 AM

Fredrik

Thanks, glad you like it!

I agree that the checked exceptions in Java are useful, however they can also be quite annoying, so overall I think I’m glad we don’t have them in C#. With Code Contracts you can introduce a CodeContract.Throws contract to define an exceptional postcondition.

I picked up the null == obj style from a code design guideline I had to follow a while back, and it has just stuck with me ever since.. just out of habit I guess Smile

Fredrik Norway

2/17/2009 11:28:02 PM

Don Smith

I was never a big C++ coder, but I think the whole null==obj thing allowed for shortcutting or some [negligible] perf gain in C++. Does not apply in Java or CLR languages from what I understand. I personally think it makes the code less readable, but that’s just me.

Nice blog.

Don Smith United States

2/25/2009 3:01:17 PM

None

null==obj is for catching the mistake obj=null

None

7/10/2009 4:08:34 AM

Xavier

Very interesting post – Might be old new, but it was new to me. Thanks.

Xavier Republic of the Philippines

7/10/2009 5:31:42 AM

Ralph

Nice blog, just bookmarked it for later reference

Ralph United Kingdom

Creating a Single Instance Application in C#

An entry about c# 3.0 | windows forms Publication date 24. March 2007 11:47

Sometimes, it’s desirable to ensure that there is only ever one instance of your application running at any given time. Take Windows Live Messenger for instance – if you try to launch it whilst it is already running, it will just bring itself to the foreground instead.

Unfortunately, a lot of people try to recreate this behavior by simply checking if a process with the same name is currently running. As K. Scott Allen explains, this is not a good idea. The correct way to implement a single instance application, is to use a named mutex.

The word mutex is short for mutual exclusion, and is a synchronisation object that can only be owned by a single thread at any given time. Specifying a name for the mutex is optional – an unnamed mutex is scoped to the current process, while a named one is associated with an operating system object and can thus be used for interprocess synchronisation. Quite simply then, we can launch our application like this:

bool createdNew = true;
using (Mutex mutex = new Mutex(true, "MyApplicationName", out createdNew))
{
if (createdNew)
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new MainForm());
}
}

That ensures that there’s only a single instance of our application running. Now, the above code just ‘does nothing’ if the application is already running – it would be nice if it instead tried to give the main window focus. To do this, we need to find the process instance, and then pinvoke the SetForeGroundWindow method of the Win32 API. Our final Main method then looks like this:

[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool SetForegroundWindow(IntPtr hWnd);
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
bool createdNew = true;
using (Mutex mutex = new Mutex(true, "MyApplicationName", out createdNew))
{
if (createdNew)
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new MainForm());
}
else
        {
Process current = Process.GetCurrentProcess();
foreach (Process process in Process.GetProcessesByName(current.ProcessName))
{
if (process.Id != current.Id)
{
SetForegroundWindow(process.MainWindowHandle);
break;
}
}
}
}
}

On a final note, I would urge you to read Raymond Chen’s excellent post “A single-instance program is it’s own denial of service”, which talks about the security implications of implementing single-instance applications.

 

4/19/2007 2:58:17 PM

Steve

Just one addition…see the discussion of protecting your mutex from garbage collection at
http://www.ai.uga.edu/mc/SingleInstance.html

Steve

4/27/2007 3:12:43 PM

Fredrik

In fact, the above solution ensures that the Mutex does not get collected – the using block keeps it in scope until the application exits Smile

Fredrik

9/12/2007 10:00:05 PM

Drunken #BeAvEr#

This works only if instance of form isn’t minimized or in system tray…
@Steve, nice solution…

Drunken #BeAvEr#

12/11/2007 11:31:59 AM

matsch

Thanks for this great post! It helped me a lot in implementing this behavior.

Still, I have a special case:
Do you know how to bring the app to front when it is hidden (i.e. residing in the system tray only). When hidden the app (or Process) does not have a MainWindowHandle, so I don’t know how to tackle this issue.

Hope you can point me in the right direction.

Thanks & best regards,
matsch

matsch

7/11/2008 2:56:25 AM

Ramki

When the window is in system tray.
By using
[DllImport(“user32.dll”)]
private static extern bool ShowWindowAsync(IntPtr hWnd, int nCmdShow);

And after SetForegroundWindow(process.MainWindowHandle);
//Call to
ShowWindowAsync(process.MainWindowHandle, 9);

Ramki

9/23/2008 3:24:08 PM

Mikes

What if the your application name is already used by another application??

Mikes United States

2/5/2009 6:04:11 PM

luke

Dont forget to add
using System.Runtime.InteropServices;
using System.Threading;

and for the 2nd part of the solution (did’nt work me me)
using System.Diagnostics;

luke United Kingdom

2/20/2009 10:58:30 PM

John Grove

What if the application can accept command line arguments to wire it up?

John Grove United States

2/23/2009 10:52:36 AM

trackback

Trackback from DotNetKicks.com

Creating a Single Instance Application in C#

DotNetKicks.com

2/24/2009 8:09:41 PM

Chris Pietschmann

On a related note, here’s an example of how to implement a Single Instance Application using WPF:
pietschsoft.com/post.aspx

Chris Pietschmann United States

3/3/2009 3:09:20 PM

Biche

This has done the trick!

Also thanks to Ramki!!

Biche Canada

3/7/2009 9:48:15 AM

ui

uyiyygdgffdrdtry

ui Argentina

4/17/2009 11:13:36 PM

Chris

Thanks! This works well. I’m trying to get the first instance to come out of the system tray. I can get it to “restore” out of the taskbar (thanks to Ramki). But how do you get it out of the system tray?

Thanks for any help, Chris

Author: Fredrik Kalseth

 

 

Say for instance that you have a class like this:

public class Test
{
    private static int InstanceCount = 0;
 
    public Test(string param)
    {
        InstanceId = ++InstanceCount;
    }
 
    public int InstanceId;
}

 

Now, assume we execute the following code:

var test1 = kernel.Get<Test>(With.Parameters.ConstructorArgument("param", "1"));
var test2 = kernel.Get<Test>(With.Parameters.ConstructorArgument("param", "2"));
var test3 = kernel.Get<Test>(With.Parameters.ConstructorArgument("param", "1"));
 
Console.WriteLine(test1.InstanceId);
Console.WriteLine(test2.InstanceId);
Console.WriteLine(test3.InstanceId);
Console.ReadLine();

 

What I want to happen here, is for the kernel to create two instances of my Test class, so that test1 and test2 test3 are the same because they passed the same transient parameter to the activation context. The output of the app then should be:

1
2
1

Notice that the first and third lines indicate that those two objects are the same instance. How can we make this happen? By creating the following binding for our Test class:

Bind<Test>().ToSelf().Using<SingletonPerVariationOfParametersBehavior>())

 

The SingletonPerVariationOfParametersBehavior (f you have an idea for a shorter name that still explains what it does let me know!) class is a custom behavior, which thanks to the great API that Ninject has only took like 10 minutes to implement. It looks like this:

/// <summary>
/// A behavior which ensures a single instance of a type exist, per variation of 
/// transient parameters in the activation context, throughout the application.
/// The variation is determined by combining the hashcodes of the implementation 
/// type and the hashcodes of transient parameter values.
/// </summary>
public class SingletonPerVariationOfParametersBehavior : BehaviorBase
{
    /// <summary>
    /// Initializes a new instance of the 
    /// <see cref="SingletonPerVariationOfParametersBehavior"/> class.
    /// </summary>
    public SingletonPerVariationOfParametersBehavior()
    {
        SupportsEagerActivation = false;
        ShouldTrackInstances = true;
    }
 
    private readonly Dictionary<int, IContext> _contextCache = new Dictionary<int, IContext>();
 
    ///<summary>
    ///Resolves an instance of the type based on the rules of the behavior.
    ///</summary>
    ///<param name="context">The activation context.</param>
    ///<returns>
    ///An instance of the type associated with the behavior.
    ///</returns>
    public override object Resolve(IContext context)
    {
        Ensure.NotDisposed(this);
 
        int hash = BuildHashForContext(context);
 
        IContext cachedContext;
 
        if (!_contextCache.TryGetValue(hash, out cachedContext))
        {
            lock (_contextCache)
            {
                if (!_contextCache.TryGetValue(hash, out cachedContext))
                {
                    context.Binding.Components.Get<IActivator>().Activate(context);
                    _contextCache.Add(hash, context);
                    cachedContext = context;
                }
            }
        }
 
        return cachedContext.Instance;
    }
 
    /// <summary>
    /// Builds a unique hash code for the context based on the implementation 
    /// type plus the transient activation parameters
    /// </summary>
    /// <param name="context">The activation context</param>
    private static int BuildHashForContext(IContext context)
    {
        int hashCode = context.Implementation.GetType().GetHashCode();
 
        foreach (Type type in context.Parameters.GetTypes())
        {
            foreach (IParameter param in context.Parameters.GetAll(type))
            {
                object value = param.GetValue(context);
 
                if (null != value) hashCode = hashCode ^ value.GetHashCode();
            }
        }
 
        return hashCode;
    }
 
    ///<summary>
    /// Releases the instance of the type contained in the context based 
    /// on the rules of the behavior.
    ///</summary>
    ///<param name="context">The activation context.</param>
    public override void Release(IContext context)
    { }
 
    ///<summary>
    /// Releases all resources held by the object.
    ///</summary>
    ///<param name="disposing"><see langword="True" /> if managed objects 
    /// should be disposed, otherwise <see langword="false" />.</param>
    protected override void Dispose(bool disposing)
    {
        if (disposing && !IsDisposed)
        {
            DestroyAll(_contextCache.Values);
            _contextCache.Clear();
        }
 
        base.Dispose(disposing);
    }
}

 

Disclaimer: Don’t trust me to have written this code without any bugs or performance bottlenecks – it’s fresh out of the oven.

1 2 3 18