Best asp.net questions in January 2012

How to make double click & single click event for link button of Asp.net control?

11 votes

Consider the following:

protected void dgTask_RowDataBound(object sender, GridViewRowEventArgs e)
{
    if (e.Row.RowType == DataControlRowType.DataRow)
    {
        LinkButton btn = (LinkButton)e.Row.Cells[4].FindControl("lnkBtnEdit");

        btn.Attributes.Add("onclick", "return Test();");
    }
}

Instead of a single click, how can I make it double click while clicking on the link button?

Edited

I have tried with the solution presented by *competent_tech* but the problem is that in that case it will intercept the single click.

I need to do some operation on single click and something else on double click. Please help me.

Thanks

You'd have to do something like this.

Code behind.

Linkbutton btn;
btn.Attributes.Add("onClick", "OnClick();");

then in your javascript you'll need to define the OnClick function like this

var clickCount = 0;
var timeoutID  = 0;

function OnClick()
{
    clickCount++;

    if (clickCount >= 2) {
       clickCount = 0;          //reset clickCount
       clearTimeout(timeoutID); //stop the single click callback from being called
       DoubleClickFunction();   //perform your double click action
    }
    else if (clickCount == 1) {
       //create a callback that will be ran in a few miliseconds
       //to allow the user time to click again if they are double clicking

       var callBack = function(){ 
                         //make sure this wasn't fired at
                         //the same time they double clicked
                         if (clickCount == 1) {      
                            clickCount = 0;         //reset the clickCount
                            SingleClickFunction();  //perform your single click action
                         }
                      };

       //This will call the callBack function in 1/2 a second.
       //If by that time they haven't clicked the LinkButton again
       //We will perform the single click action. You can adjust the
       //Time here to control how quickly the user has to double click.
       timeoutID = setTimeout(callBack, 500); 
    }
}

You can either put the javascript directly into your .aspx file or add it dynamically when you add the LinkButton to the page. If you need to perform some action on the server side when the user single clicks or double clicks you can use the __doPostBack method. See here for more info on that.

The problem with my approach is that the user will always have to wait the entire callback time before their single click action is performed. I don't see any way around this as long as you are using single click/double click to distinguish what the user wants. If you find this delay to be too big of a problem you could always try something like click/shift+click to alternate between the actions. It probably wouldn't be as intuitive that way but you would immediately know what the user wants and could respond immediately instead of waiting to see if the user clicks a second time.

Let me know if you have any questions.

How do extension methods work under-the-hood?

11 votes

A contractor where I work is using extension methods to implement CRUD on well-known internal classes that we own. I say it is better to use normal inheritance over extension methods for the following reasons.

  • Using extension methods obfuscates & confuses the source of the CRUD methods.
  • I assume extension methods make heavy use of reflection (which is slower).

His logic is, "It's compiled, so it's fast." Maybe I'm wrong...but just because it is compiled doesn't mean it doesn't use reflection, nor does it mean it is faster than normal inheritance.

So my questions are:

  1. How do extension methods work under-the-hood?
  2. Is it better to use inheritance or extension methods on WELL-KNOWN classes that you OWN?

How do extension methods work under-the-hood?

They're just static methods; the compiler rewrites calls like myObject.MyExtensionMethod() to MyExtensionClass.MyExtensionMethod(myObject).

Is it better to use inheretance or extension methods on WELL-KNOWN classes that you OWN?

There's not single answer to this question, it all depends on the context. But usually extension methods are most useful in those cases:

  • you don't own the code for the extended type
  • the method targets an interface and will be the same for all implementations of this interface (e.g. IEnumerable<T> and Linq extension methods)

comment between else and {

10 votes

I just started using Razor instead of the WebForms-ViewEngine. Now in my Razor-View i have something like this:

@{
  int i = 42;
  string text;
  if (i == 42)
  {
    text = "i is 42!";
  }
  else //i is not 42 //<- Error here
  {
    text = "i is something else";
  }
}

I get a warning and at runtime it get an exception in the else line:

Expected a "{" but found a "/". Block statements must be enclosed in "{" and "}". You cannot use single-statement control-flow statements in CSHTML pages.

Apparently the compiler doesn't like comments between the else and the {. I also tried commenting with @* and /*, which gave similar error-messages.

Is there anyway to make a comment in razor like I want it?


Disclaimer:

Yes i know i could fix it simply like this:

@{
  int i = 42;
  string text;
  if (i == 42)
  {
    text = "i is 42!";
  }
  else
  { //i is not 42
    text = "i is something else";
  }
}

However it doesn't fit our coding guidelines and having the comment on the same line makes my intentions more clear.

That's how the Razor parser is built. You could always submit a bug/feature request on MS connect if you don't like the way it is and hope that people will vote for it and it will be fixed/implemented in a future version of the parser. Personally I wouldn't because I don't care (see below why).

This being said, why care? I mean you are not supposed to write code in a Razor page. A Razor page is intended to be used as a view. In ASP.NET MVC a view is used to display some information from the view model that is passed to it from the controller action. Markup primary, mixed with HTML helpers and displaying information from the view model. But C# code is a no no. So what you call code and what you have shown in your question has strictly nothing to do in a Razor view.

Migrating bad system into our current system with tons of data

10 votes

I inherited of a system when my company bought another company. This system is a mix of LAMP and .NET.

  1. 1 Windows server running asp.net that controls third-party validation used only for apis and webservice - (let's call it WIN)
  2. 8 LAMP servers (web, reports, cron, repositories etc...) - (let's call it NEW)

Our current environment:

14 LAMP servers (web, mail, repositories, etc...) - (let's call it CURRENT)

The good news is the NEW code is pretty straigt foward. A few millions lines of code (which most are apis, third party) and I can convert it to the CURRENT system. The NEW and CURRENT use both CentOs which will make the transision easy, except the Windows server that I have no idea what to do now.

Now the bad news. The NEW system database schema is not good at all. It is not normalized and the queries are slow (database queries and the code too). My first idea is to redesign them to a more normalized structure that matches the CURRENT code but I don't work. The tables from the NEW system are gigantic. The NEW system has 7 databases, over 10000 tables, the smallest tables have over 100k rows and some tables have over 500 millions rows. One of the database has most of the tables with over 25 millions rows each.

Is it safe to migrate or should I keep both running? If I should migrate I want to know what will the safest solution for me in order to migrate the Windows and NEW system into my CURRENT system?

First of all, moving the WIN + NEW systems into the CURRENT system will take time. so you have to make sure when you start migrating/converting everything, you know where you going. Migrating might not be an easy task and you can run into issues you never thought after you started the process.

Your idea of migrating the NEW system has pros and cons and you need to make sure it goes smoothly in order to get a good and reliable product at the end.

Pros:

  • only one system to maintain: you don't want to maintain 3 systems;
  • one code/database environement: PHP vs ASP.NET and MSSQL vs MySQL;
  • centralized code/database;
  • one coding (code and database) standard;
  • save/sell equiments (you will migrate the code to your 14 servers, maybe you don't need the other 9 (WIN+NEW), so you can sell or keep them for the next projects)

cons:

  • higher risk (crash, incompatibility, unknown feature you need to understand etc..);
  • cheaper than migrating or re-designing everything
  • risk of failure is lower than migration (since you already know both system works)
  • planning, control, implementation, quality assurance: very bad if one of these fail;
  • expensive: migrating can be expensive in time and money;

This is a big database, changing/optimizing this will take a significant investment in labor hours. This is not something you can easily do in few hours. This can take weeks maybe months in order to successfully migrate data to the CURRENT system without errors. If you can, you can start by migrating common or similarities from both database schema, like clients or products. This way, you import data that the CURRENT system can run without errors and also your code will recognise. The users of your CURRENT system can immediately start managing these items/records without issue. As of new or records your CURRENT system does not recognise, you can simply re-design these tables and migrate them to the CURRENT system (then update your current code).

As of code migration, if the code from the NEW system is good enough and match your standard you can keep it. This will save time in development, just make sure you update the queries and servers connections. On the other hand, if it's like spaghetti code, you will have to understand what the code do. This can also take a significant investment in labor hours. I can recommend here to standardize this one and organize your code the same way you organize it on the CURRENT one. You can centralize your code in one common folder using a common file and folder structure. You can put all your common libraries, 3rd parties etc.. there so when you call the CURRENT and the NEW code, it loads the same PHP class. This will make your ease your transitions from the NEW to CURRENT system. This way, you know all your required files at in the same place and very easy to maintain. Specially if your code requires required files that requires files. If you code is all around your servers, you can create an NFS if you like this idea.

Now, what I can suggest is to start with a Parallel Adoption . This way you make sure all systems are working properly and are healthy. Then slowly migrate data/code to the CURRENT system until everything is completed. This won't be easy and you have to identify which part of the NEW + WIN systems you have to migrate first. My recommendation will be to migrate the WIN system. Because this is independent of the CURRENT and NEW systems, as long you display the same output you should be fine. Search for open source or similar validations in PHP or if you can't find any, build them. This way this WIN system can easily be migrated to your current organization structure and coding standards. Performing tests and quality assurances will be easy and you can be completed very quickly.

Once this WIN is migrated, you need to identify what you need to transfer first to the CURRENT system. For example, if the NEW and CURRENT system has "clients", gather all the information from the NEW system and move them to the CURRENT system using a script (manually or scripted). Then, you can migrate clients elements like products, billing statement or any other records that are related to these clients). Repeat these steps until all the data are migrated. This way, you don't have to re-design any tables or change any codes from the NEW system, everything is saved on the CURRENT system and everything works correctly.

I won't recommend the big bang adoption for this case .

How can i make a disabled control back to enable using Javascript

8 votes

I have done a code to disable a control when user clicks on a control. On my form i am having a TextBox and a DropDown. When user clicks on a TextBox i will disable the DropDown like that when click on DropDown i will disable the TextBox which works fine.

But when the user clicks on Disabled control i would like to enable that control. Means if i click on TextBox which was disabled i would like to Enable it like that for dropdown too..

My sample Script is as follows

<script type="text/javascript">

function toggleDropDownList1()
{
var d=document.getElementById("<%= DropDownList4.ClientID %>");
if(d.disabled)
{
d.disabled=false;
}
else
{
 document.getElementById("<%= TextBox1.ClientID %>").disabled = true;
}
}
function toggleDropDownList2()
{
 document.getElementById("<%= DropDownList4.ClientID %>").disabled = true;
}
</script>

Design

<asp:TextBox ID="TextBox1" runat="server" onclick="toggleDropDownList2();"></asp:TextBox>
        <asp:DropDownList ID="DropDownList4" runat="server" onclick="toggleDropDownList1();">
            <asp:ListItem Text="One" Value="1"></asp:ListItem>
            <asp:ListItem Text="One" Value="1"></asp:ListItem>
        </asp:DropDownList>

The idea is to place a div in front of dropdown list, and this div accept the onclick event.

The issue here is that the div can not place so easy in front of dropdown list. To place it you need to do that dynamically and use the absolut position.

I make here a small code, and test it and working. I have left the background color RED on div to see where it is. Some details I left it to you, eg to find the width and height of your control list, I place the onclick, you can place back the double click, And just remove the red background.

<script type="text/javascript">
function toggleDropDownList1()
{
    var MyDiv = document.getElementById("DivForClick");
    MyDiv.style.display = "none";

    var d=document.getElementById("<%= DropDownList4.ClientID %>");
    if(d.disabled)
    {
        d.disabled=false;
    }
    else
    {
        document.getElementById("<%= TextBox1.ClientID %>").disabled = true;
    }
}

function toggleDropDownList2()
{
    document.getElementById("<%= DropDownList4.ClientID %>").disabled = true;

    var MyDdl = document.getElementById("<%= DropDownList4.ClientID %>");
    var MyDiv = document.getElementById("DivForClick");

    MyDiv.style.display = "block";
    MyDiv.style.left = MyDdl.style.left;
    MyDiv.style.top = MyDdl.style.top;

    // need to find the height/width
    // MyDiv.style.height = MyDdl.style.height;
    // MyDiv.style.width = MyDdl.style.width;   
}
</script>

and the asp code.

<asp:TextBox ID="TextBox1" runat="server" onclick="toggleDropDownList2();"></asp:TextBox>

<br /><br />

<div id="DivForClick" onclick="toggleDropDownList1();" style="z-index:999;position:absolute;left:0;top:0;height:20px;width:40px;background-color:Red;display:none;">
</div>

<asp:DropDownList ID="DropDownList4" runat="server" onclick="toggleDropDownList1();" style="z-index:2;">
   <asp:ListItem Text="One" Value="1"></asp:ListItem>
   <asp:ListItem Text="Two" Value="2"></asp:ListItem>
</asp:DropDownList> 

How can I stop a postback from refreshing the page at the client

7 votes

When I start a postback using __doPostBack, a file is created and going back to the user to download in the HttpContext.Current.Response.

Because I change the Response, the page including its javascript values is not modified

But when I have no file to output, the page is refreshed (because of the postback) and the javascript modification on the page are lost.

How can I 'stop' the postback from continuing and persist my current page? I can't use an async postback, because I need the postback to let the user download the file.

EDIT: more info after some questions in the comments:

  • The file is requested in a webservice request. The webservice needs to execute a heavy query to determine if a file will be created. I prefer that this only happens once.
  • The user can drag / drop some filters that will be used in the file request. If no file is available, the user should be able to change his filters, so thats why the page should not be changed.

From the W3 standards and RFC 2616:

10.2.5 204 No Content The server has fulfilled the request but does not need to return an entity-body, and might want to return updated metainformation. The response MAY include new or updated metainformation in the form of entity-headers, which if present SHOULD be associated with the requested variant.
If the client is a user agent, it SHOULD NOT change its document view from that which caused the request to be sent. This response is primarily intended to allow input for actions to take place without causing a change to the user agent's active document view, although any new or updated metainformation SHOULD be applied to the document currently in the user agent's active view. The 204 response MUST NOT include a message-body, and thus is always terminated by the first empty line after the header fields.

Note the bolded line here. I have not tried it myself; however, setting the HTTP status to 204 and sending back an empty document, rather than trying to stop postback entirely, is certainly worth a shot.

Good luck, I hope this helps.

EDIT: this is the code that does the trick:
System.Web.HttpContext.Current.Response.StatusCode = 204;

String Fraction to Double

7 votes

I need a function to parse a user inputs of numbers to doubles. I cannot do anything client side or change how the input comes in.

Input       | Desired Output
"9"         | 9
"9 3/4"     | 9.75
" 9  1/ 2 " | 9.5
"9 .25"     | 9.25
"9,000 1/3" | 9000.33
"1/4"       | .25

I saw this post, but it uses Python, I was just wondering if anybody knew any fancy C# ways of handling this before I spend time to write my own.

Here's what I ended up using:

private double ParseDoubleFromString(string num)
{
    //removes multiple spces between characters, cammas, and leading/trailing whitespace
    num = Regex.Replace(num.Replace(",", ""), @"\s+", " ").Trim();
    double d = 0;
    int whole = 0;
    double numerator;
    double denominator;

    //is there a fraction?
    if (num.Contains("/"))
    {
        //is there a space?
        if (num.Contains(" "))
        {
            //seperate the integer and fraction
            int firstspace = num.IndexOf(" ");
            string fraction = num.Substring(firstspace, num.Length - firstspace);
            //set the integer
            whole = int.Parse(num.Substring(0, firstspace));
            //set the numerator and denominator
            numerator = double.Parse(fraction.Split("/".ToCharArray())[0]);
            denominator = double.Parse(fraction.Split("/".ToCharArray())[1]);
        }
        else
        {
            //set the numerator and denominator
            numerator = double.Parse(num.Split("/".ToCharArray())[0]);
            denominator = double.Parse(num.Split("/".ToCharArray())[1]);
        }

        //is it a valid fraction?
        if (denominator != 0)
        {
            d = whole + (numerator / denominator);
        }
    }
    else
    {
        //parse the whole thing
        d = double.Parse(num.Replace(" ", ""));
    }

    return d;
}

Replace selected content in the ckEditor with new content using javascript

6 votes

I am using CKEditor ver.3.6 in my MVC Application.

My requirement is to update the selected text with new text in the ckEditor. I could find out the method editor.getSelection().getSelectedText(); for getting selected text from the editor. I need to add some tag with the selected text when a toolbar button is pressed and update the selected content using javascript.

For Example :

Content in the ckEditor is

 <span>Edit content in the editor</span>

and I have selected the word “editor” from ckEditor. I have to update the selected word “editor” with “ckEditor” using javascript code.

Please suggest a proper solution.

It looks to me from the docs as the following would work (untested):

editor.insertText("ckEditor");

When will ASP.NET kill a new thread?

6 votes

I've tried some googling on this subject but i would like to have som more info.

I'm trying to start a new thread inside an ASP.NET app that will take care of some work that takes long time. If I put this in my web.config:

<httpRuntime executionTimeout="5" />

A regular request will timeout after 5 secounds. Remember this is for testing. When I start a new thread from the code:

    var testThread = new Thread(new ThreadStart(CustomClass.DoStuffThatTakesLongTime));
    testThread.Start();

This thread will run for longer than 5 secounds, that's what I want. BUT. For how long will it run? Let's say this thread takes 5h (just as an example). When will the thread be killed? Will it run until the app pool is recycled? Or is there anything else that kills this thread?

ASP.NET has no knowledge of the thread that you have created - it will run until the AppPool is recycled or it completes.

Since ASP.Net has no knowledge of this thread however, it could be aborted quite abruptly at any point if the server thinks that it should recycle the AppPool, this would not be a good thing! Phil Haack wrote a blog post on how to subscribe to the 'AppDomainIsGoingDown' event.

In regards to what can cause this, I'd recommend reading this blog post by Tess Ferrandez, but in a nutshell they are:

  • It has been scheduled to do so
  • Machine.Config, Web.Config or Global.asax are modified
  • The bin directory or its contents is modified
  • The number of re-compilations (aspx, ascx or asax) exceeds the limit specified by the setting in machine.config or web.config (by default this is set to 15)
  • The physical path of the virtual directory is modified
  • The CAS policy is modified
  • The web service is restarted
  • (2.0 only) Application Sub-Directories are deleted

'Operation is not valid due to the current state of the object' error during postback

6 votes

I had a aspx page which was working good. Suddenly i am getting this error "Operation is not valid due to the current state of the object." whenever a post back is done.

the stack trace is

at System.Web.HttpValueCollection.ThrowIfMaxHttpCollectionKeysExceeded() at System.Web.HttpValueCollection.FillFromEncodedBytes(Byte[] bytes, Encoding encoding) at System.Web.HttpRequest.FillInFormCollection()

Can someone help?

somebody posted quite a few form fields to your page. The new default max introduced by the recent security update is 1000.

Try adding the following setting in you web.config's <appsettings> block. in this block you are maximizing the MaxHttpCollection values this will override the defaults set by >net Framework. you can change the value accordingly as per your form needs

<appSettings>
    <add key="aspnet:MaxHttpCollectionKeys" value="2001" />
 </appSettings>

for more information please read this post. For more insight into the security patch by microsoft you can read this Knowledge base article

Should the UI layer be able to pass lambda expressions into the service layer instead of calling a specific method?

6 votes

The ASP.NET project I am working on has 3 layers; UI, BLL, and DAL. I wanted to know if it was acceptable for the UI to pass a lambda expression to the BLL, or if the UI should pass parameters and the Service method should use those parameters to construct the lambda expression? Here is an example class showing both senarios.

public class JobService 
{
    IRepository<Job> _repository;

    public JobService(IRepository<Job> repository) 
    {
        _repository = repository;
    }

    public Job GetJob(int jobID)
    {
        return _repository.Get(x => x.JobID == jobID).FirstOrDefault();
    }

    public IEnumerable<Job> Get(Expression<Func<Job, bool>> predicate)
    {
        return _repository.Get(predicate);
    }
}

For the above class is it acceptable for the UI to call the following:

JobService jobService = new JobService(new Repository<Job>());
Job job = jobService.Get(x => x.JobID == 1).FirstOrDefault();

or should it only be allowed to call GetJob(int jobID)?

This is a simple example, and my question is in general, should the UI layer be able to pass lambda expressions into the service layer instead of calling a specific method?

This is a judgement call based on the situation. It's not necessarily wrong to pass in a predicate like this. I think it should be considered a minor bad smell though.

If the passing in of a lambda expression allows you to reduce 6 methods down to 1, then it might be a good move. On the other hand, if you can just as easily pass in a simple type, then lambda syntax is a needless complication.

In the above example, not knowing the context, my preference would be to use a simple integer parameter. There should usually be a basic method that just gets a record by it's ID. And maybe one or two other such methods that are repeatedly used through your application. And then maybe a general purpose method that takes a lambda.

You should also consider what some would suggest should be a rule: that you not have any methods with lambda-specified predicates between your UI and your business layer. (And some believe, with reason, that your repositories shouldn't even have such methods!) I don't believe this should be an iron-clad rule, but there's good reasons for it. Your business and data layers, between them, should keep dangerous queries from happening. If you allow the passing in of lambdas, it's very easy for a junior developer in the UI layer to specify queries that could really hose your database. (For example, they'll do huge queries against non-indexed fields, and/or filter against the resultset using LINQ-to-objects, and not realize how inefficient that is.)

Like many other good practices, this will depend somewhat on scope. In my recent large application, I have no passing of lambda syntax from the UI layer to the business layer. My plan was to invest heavily in the business layer, to make it very smart. It has all the needed methods with simple types. In fact, it typically gives you what you need through simple domain object properties, with no parameters at all. My interface assures that the UI can only cause efficient queries to happen, with perhaps just minor LINQ-to-Objects predicates in the UI layer. (This goes even for "search" pages. My business layer accepts a criteria object with constrained possibilities, and ensures an efficient query.)

Now, you said "layers", rather than "tiers". So these are all in the same assembly? Another disadvantage of lambda is they're (currently) difficult to serialize. So you'd regret them if you had to separate your tiers.

How does Internationalization in ASP.NET work?

4 votes

I wonder if it is possible to make your application multilingual by simply creating resource files for every required language
Like

Resource.resx for English      //string abc(name)=xyz(value)
Resource.zh.resx for Chinese   //string abc(name)=zh(value)

And simply placing a string in your view(single view only that support multilingual) string like

@appName.Resource.abc

and

<globalization culture="en-GB" uiCulture="auto:en-GB" />

in Web.Config

Now my question is

Is this enough to get started with multilingual sites i.e if I change the preferred language in my browser to Chinese the content of page is changing? But how does this work?

What I know is

  • Browser returns preferred culture list

Need to know - How mapping to particular resource file take place. I mean both resource files (Resource.resx and Resource.zh.resx) in my example have an 'abc' property with different value. How does asp.net figure out which value to render? Is there any naming convention?

At run time, ASP.NET uses the resource file that is the best match for the setting of the CurrentUICulture property. The UI culture for the thread is set according to the UI culture of the page. For example, if the current UI culture is Spanish, ASP.NET uses the compiled version of the WebResources.es.resx file. If there is no match for the current UI culture, ASP.NET uses resource fallback. It starts by searching for resources for a specific culture. If those are not available, it searches for the resources for a neutral culture. If these are not found, ASP.NET loads the default resource file. In this example, the default resource file is WebResource.resx.

Ref: ASP.NET Web Page Resources Overview

Microsoft .NET Internationalization

How can i attach Calender(Global) on click event of textbox?

4 votes

How can i attach Calender(Global) on click event of textbox in dd-mm-yyyy format??
I am using Internationalization and want a user to select date in DD-MM-YYYY format as Date Of birth with specific culture.
With Specific culture i mean to display calender in particular language like if CurrentCulture is China then calendar must look like this but in parts


And if CurrenCulture is English then Calendar is like



Updated


In short i need Global datePicker Calender on Textfield

Check this blog from ScottGu. It has explained how to do the culture in javascript using jQuery.

Hope this helps you.

Some other links

http://jquery-howto.blogspot.com/2010/10/jquery-globalization-plugin.html

http://jquery-howto.blogspot.com/

http://www.hanselman.com/blog/GlobalizationInternationalizationAndLocalizationInASPNETMVC3JavaScriptAndJQueryPart1.aspx

Data passing between the ASP.NET MVC 3 view hierarchy

4 votes

Motivation

I want to be able to build up a tree-like object hierarchy in Javascript that corresponds to the ASP.NET MVC 3 Razor views on a page. The plan is to have a one-to-one correspondence between a Razor view and a Javascript file where its logic is defined (in form of a constructor function that will accept some initialization parameters). Simple example could look like this :

  • _Layout.cshtml <-> Global.js
    • SplitterPane.cshtml <-> SplitterPane.js
      • Grid.cshtml <-> Grid.js
      • Tree.cshtml <-> Tree.js

I would use the constructors to build a hierarchy, e.g.

var page = new Global(global_options);
var splitter = new SplitterPane(splitter_options);
var grid = new Grid(grid_options);
var tree = new Tree(tree_options);

page.addChild(splitter);
splitter.addChild(grid);
splitter.addChild(tree);

All of this code should be of course constructed automatically in the context of the root (layout) view from metadata collected from the partial views. Metadata provided by a view contains the options necessary to initialize its Javascript object and the Javascript files to load.

Problem

Unlike WebForms, MVC views do not have any natural hierarchy I would know of and passing information between a view and its partial (sub)views seems rather tricky. In case of using helpers like Html.Action in the view the whole processing of a "subview" happens independently, so they don't even share the Page object. What I need is some kind of a central place where the views can deposit their metadata as they are rendered so that it can be used in the layout view to combine and output the complete script.

Solution ?

One way I could think of was to use the HttpContext.Current.Items to temporarily store a collection of view metadata objects. All the views would deposit the metadata there and layout view would use it. The order of execution seems to match my expectation, however I'm still unable to reconstruct the tree hierarchy of views. To be able to do that, I would need to use a stack where a view would register on start of its rendering and unregister on the end, so that the parent can be found on the top.

  1. Is there a way to have some pre-/post-render hooks where I could put this logic ?
  2. Is this even a good idea in the first place ?
  3. Is there a completely different solution that I don't see ?

You could write a custom view engine:

public class MyViewEngine : RazorViewEngine
{
    private class MyRazorView : RazorView
    {
        public MyRazorView(ControllerContext controllerContext, string viewPath, string layoutPath, bool runViewStartPages, IEnumerable<string> viewStartFileExtensions, IViewPageActivator viewPageActivator)
            : base(controllerContext, viewPath, layoutPath, runViewStartPages, viewStartFileExtensions)
        {
        }

        protected override void RenderView(ViewContext viewContext, System.IO.TextWriter writer, object instance)
        {
            var stack = viewContext.HttpContext.Items["stack"] as Stack<string>;
            if (stack == null)
            {
                stack = new Stack<string>();
                viewContext.HttpContext.Items["stack"] = stack;
            }
            // depending on the required logic you could
            // use a stack of some model and push some additional
            // information about the view (see below)
            stack.Push(this.ViewPath);
            base.RenderView(viewContext, writer, instance);
        }
    }

    protected override IView CreateView(ControllerContext controllerContext, string viewPath, string masterPath)
    {
        return new MyRazorView(controllerContext, viewPath, masterPath, true, base.FileExtensions, base.ViewPageActivator);
    }

    protected override IView CreatePartialView(ControllerContext controllerContext, string partialPath)
    {
        return new MyRazorView(controllerContext, partialPath, null, false, base.FileExtensions, base.ViewPageActivator);
    }
}

that you would register in Application_Start:

ViewEngines.Engines.Clear();
ViewEngines.Engines.Add(new MyViewEngine());

and now you can write a custom HTML helper that will pick the stack that was stored in the HttpContext and do something useful:

public static class HtmlExtensions
{
    public static IHtmlString BuildTree(this HtmlHelper htmlHelper)
    {
        var stack = htmlHelper.ViewContext.HttpContext.Items["stack"] as Stack<string>;
        if (stack == null)
        {
            return MvcHtmlString.Empty;
        }


        // TODO: your custom logic to build the tree
        ...
    }
}

and in the end of your _Layout:

    ...
    <script type="text/javascript">
        @Html.BuildTree()
    </script>
</body>

How to hide unselected items on a checkboxlist?

4 votes

I have a checkboxlist which gets the data from XML file. If a user selects an item on checkboxlist, i just want to show that item and hide everything else. And beneath that, I want to add clickable text to let the use to choose something else. So if the use click on that text, the user will see the checkboxlist again with the first item selected.

Basically look like this. exampe So how do we achieve this?

Thanks so much.

require to use vb.net/and checkboxlist control as we will be databinding dynamically from database.

Here is one way. Use two Panels as container for two different CheckBoxLists. The first displays your "FROM"-Items and the latter your "TO"-Items.

The second panel is initially invisivle. Apart from the CheckBoxList it contains a LinkButton to trigger the deselection.

On BtnSelect-Click you'll add the selected items from the first to the second CheckBoxList and show it's Panel. On BtnChangeSelection-Click you only need to switch visibiliy of both Panels and select first item.

This already works with multiple selection.

ASPX (CSS is up to you):

<div>
    <asp:Panel ID="PnlChkListAcademicYear" runat="server">
        <asp:CheckBoxList ID="ChkListAcademicYear" runat="server" /><br />
        <asp:LinkButton ID="BtnSelect" Text="Select" runat= "server" ></asp:LinkButton>
    </asp:Panel>
    <asp:panel ID="PnlChkListAcademicYearActive" Visible="false" runat="server">
        <asp:CheckBoxList ID="ChkListAcademicYearActive" Enabled="false" runat="server" /><br />
        <asp:LinkButton ID="BtnChangeSelection" Text="Change selection" runat= "server" ></asp:LinkButton>
    </asp:panel>
</div>

Codebehind:

Private Sub BtnSelect_Click(sender As Object, e As System.EventArgs) Handles BtnSelect.Click
    If Me.ChkListAcademicYear.SelectedIndex <> -1 Then
        Dim selectedItems = (From item In Me.ChkListAcademicYear.Items.Cast(Of ListItem)() Where item.Selected).ToArray
        Me.ChkListAcademicYearActive.Items.Clear()
        Me.ChkListAcademicYearActive.Items.AddRange(selectedItems)
        Me.PnlChkListAcademicYearActive.Visible = True
        Me.PnlChkListAcademicYear.Visible = False
    End If
End Sub

Private Sub BtnChangeSelection_Click(sender As Object, e As System.EventArgs) Handles BtnChangeSelection.Click
    Me.ChkListAcademicYear.SelectedIndex = 0
    Me.PnlChkListAcademicYearActive.Visible = False
    Me.PnlChkListAcademicYear.Visible = True
End Sub

This is the rest of my sample-code, for the sake of completeness:

Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
    If Not IsPostBack Then
        BindCheckboxList()
    End If
End Sub

Private Sub BindCheckboxList()
    Me.ChkListAcademicYear.DataSource = GetData()
    Me.ChkListAcademicYear.DataTextField = "Year"
    Me.ChkListAcademicYear.DataBind()
End Sub

Private Function GetData() As DataTable
    Dim years = {"2010/2009", "2009/2008", "2008/2007", "2007/2006", "2006/2005", "2005/2004", "2004/2003"}
    Dim tbl = New DataTable
    tbl.Columns.Add(New DataColumn("Year"))
    For Each y In years
        tbl.Rows.Add(y)
    Next
    Return tbl
End Function

Convert a traditional post in ajax

4 votes

Suppose I have a form :

<form id="myForm" method="POST" action="/something/somewhere">
   <input type="text" name="textField" />
   <input type="submit" name="foo" value="bar" />
</form>

the /something/somewhere action does not return a complete html page, but just a fragment.

I would like to let the submit button do its posting job, but catch the result of this post and inject it somewhere in the DOM.

The jQuery submit happens before the form is actually submitted. An exemple of how it could work is:

$('#myForm').posted(function(result)
{
    $('#someDiv').html(result);
});

Any way to do this?

Description

You can use the jQuery .post() and .serialize() method for that.

.post() Load data from the server using a HTTP POST request.

.serialize() Encode a set of form elements as a string for submission.

.preventDefault() If this method is called, the default action of the event will not be triggered. In your case the normal submit.

Sample

Html

<form id="myForm" method="POST" action="/My/MyActionMethod">
   <input type="text" name="textField" />
   <input type="submit"/>
</form>

<div id="someDiv"></div>

jQuery

$(function() {
  $('#myForm').live('submit', function (e) {
     var form = $(this);
     e.preventDefault();
     $.post(form.attr('action'), form.serialize(), function (result) {
        $('#someDiv').html(result);
     });
  });
});

MVC Controller

public class MyController : Controller
{
    [HttpPost]
    public ActionResult MyActionMethod(FormCollection forms)
    {
        // do something with forms["textField"];
        return Content("<b>Hello World!</b>");
    }
}

If you have trouble getting it to work (thanks IE), try

event.preventDefault ? event.preventDefault() : event.returnValue = false;

More Information

Why can't I use server controls in ASP.net MVC?

4 votes

I'm getting ready to be responsible for leading the development of a small ASP.net MVC application. This is my first time creating an MVC application, so I am excited!

I've carefully read over the documentation and I feel like I have the general idea of how MVC works. However, if I understand correctly, server controls (like GridView, for instance) are not part of MVC.

My question is: Why? At my development shop, I'm so used to using controls like GridView and the MS Chart Controls that I'm almost at a complete loss as to developing without them. It seems almost like starting over.

Why are the server controls unavailable? How does Microsoft expect me to work without them? What are the alternatives?

My question is: Why?

Because most of them depend on things like ViewState and the Postback models which are part of the classic WebForms model and no longer exist in ASP.NET MVC. Those server side controls rely on events that will perform postbacks to the server persisting their state in hidden fields (ViewState). In ASP.NET MVC you no longer work with events such as Button1_Click. In ASP.NET MVC you work with a Model, a Controller and View. The Controller is responsible for receiving user requests, querying the Model, translating the results into a view model and passing this view model to the View whose responsibility is to display it under some form.

In ASP.NET MVC there are HTML helpers that could be used to generate some reusable HTML fragments between views. You may take a look for example at the Telerik ASP.NET MVC suite of such helpers. They call them controls but they have nothing to do with classic WebForms server side controls. They are just HTML helpers.

Basically classic WebForms are a leaky abstraction of the web. What Microsoft did back in the time when they designed this framework was to bring existing Windows developer skills to the web which was getting more and more momentum. But since the web was still a new technology that most developers weren't yet familiar with, they created this abstraction to hide away the way that the www works. Those developers were accustomed to drag and dropping controls on their Windows Forms, double clicking on buttons that was generating some code for them in which they put their data access logic and so on. This model was transposed to web application development thanks to WebForms. The HTTP protocol was successfully hidden behind this abstraction called WebForms. For example you don't need to know HTML, nor Javascript, not even CSS in order to create a website using WebForms which is really great because the framework abstracts all those things for you. Unfortunately by doing so it prevents you from easily utilizing the full power of lower level web technologies which some people might need when developing web applications.

What ASP.NET MVC does is basically remove this leaky abstraction and bring the www to the developers the way it was intended to be by its creators. ASP.NET MVC is not mature enough compared to classic WebForms so you cannot expect to find the same range of available controls and widgets but things are slowly shifting.

I would recommend you start here with ASP.NET MVC: http://asp.net/mvc. Go ahead, watch the videos, play around with the samples and see if ASP.NET MVC is for you or not. And of course if you encounter some specific difficulty or question don't hesitate to come back here and ask it.

FormsAuthenticationModule Authenticate event not firing when using ASP.NET MVC

4 votes

We are using the HttpModule to hook in to the FormsAuthenticationModule and subscribe to the Authenticate event. When we use web forms this event fires in the module. When we are using MVC this event is not firing.

I have tried using the [Authorize] attribute on the Controllers and location in web.config (even though this isn't best practice) to try and get this event to fire but it still does not.

The event does fire when using the Cassini webserver but does not fire on IIS 7.5 or IIS Express. We are running ASP.NET MVC 2 using .NET 3.5

EDIT

The Authentication event fires when we request a .aspx or .ashx file. If we request an extensionless file or a .css or .js it does not fire either.

An new ASP.NET MVC application will fire this event for every file requested.

Any suggestions?

Our web.config was missing the runAllManagedModulesForAllRequests="true" from the modules element in system.webServer. Once this was added all web requests receive the Authorisation event from FormsAuthenticationModule.

<system.webServer>
    ....
    <modules runAllManagedModulesForAllRequests="true">
    ....
</system.webServer>