Best asp.net questions in March 2012

Partial work being done twice (ThreadPool.QueueUserWorkItem)

9 votes

I have created a newsletter system that allows me to specify which members should receive the newsletter. I then loop through the list of members that meet the criteria and for each member, I generate a personalized message and send them the email asynchronously .

When I send out the email, I am using ThreadPool.QueueUserWorkItem.

For some reason, a subset of the members are getting the email twice. In my last batch, I was only sending out to 712 members, yet a total of 798 messages ended up being sent.

I am logging the messages that get sent out and I was able to tell that the first 86 members received the message twice. Here is the log (in the order the messages were sent)

No.  Member   Date
1.   163992   3/8/2012 12:28:13 PM
2.   163993   3/8/2012 12:28:13 PM
...
85.   164469   3/8/2012 12:28:37 PM
86.   163992   3/8/2012 12:28:44 PM
87.   163993   3/8/2012 12:28:44 PM
...
798.   167691   3/8/2012 12:32:36 PM

Each member should receive the newsletter once, however, as you can see member 163992 receives message #1 and #86; member 163993 received message #2 and #87; and so on.

The other thing to note is that there was a 7 second delay between sending message #85 and #86.

I have reviewed the code several times and ruled out pretty much all of the code as being the cause of it, except for possibly the ThreadPool.QueueUserWorkItem.

This is the first time I work with ThreadPool, so I am not that familiar with it. Is it possible to have some sort of race-condition that is causing this behavior?

=== --- Code Sample --- ===

    foreach (var recipient in recipientsToEmail)
    {
        _emailSender.SendMemberRegistrationActivationReminder(eventArgs.Newsletter, eventArgs.RecipientNotificationInfo, previewEmail: string.Empty);
    }


    public void SendMemberRegistrationActivationReminder(DomainObjects.Newsletters.Newsletter newsletter, DomainObjects.Members.MemberEmailNotificationInfo recipient, string previewEmail)
    {
//Build message here .....

//Send the message
            this.SendEmailAsync(fromAddress: _settings.WebmasterEmail,
                                toAddress: previewEmail.IsEmailFormat()
                                            ? previewEmail
                                            : recipientNotificationInfo.Email,
                                subject: emailSubject,
                                body: completeMessageBody,
                                memberId: previewEmail.IsEmailFormat()
                                            ? null  //if this is a preview message, do not mark it as being sent to this member
                                            : (int?)recipientNotificationInfo.RecipientMemberPhotoInfo.Id,
                                newsletterId: newsletter.Id,
                                newsletterTypeId: newsletter.NewsletterTypeId,
                                utmCampaign: utmCampaign,
                                languageCode: recipientNotificationInfo.LanguageCode);
        }

    private void SendEmailAsync(string fromAddress, string toAddress, string subject, MultiPartMessageBody body, int? memberId, string utmCampaign, string languageCode, int? newsletterId = null, DomainObjects.Newsletters.NewsletterTypeEnum? newsletterTypeId = null)
    {
        var urlHelper = UrlHelper();
        var viewOnlineUrlFormat = urlHelper.RouteUrl("UtilityEmailRead", new { msgid = "msgid", hash = "hash" });
        ThreadPool.QueueUserWorkItem(state => SendEmail(fromAddress, toAddress, subject, body, memberId, newsletterId, newsletterTypeId, utmCampaign, viewOnlineUrlFormat, languageCode));
    }

Having 800+ threads running on the server is not a good practice! Although you are using a ThreadPool, threads are being queued on the server and run whenever old threads return back to the pool and release the resource. This might take several minutes on the server and many situations like Race Conditions or Concurrencies might happen during that time. You could instead queue one work item, over one protected list:

lock (recipientsToEmail)
{
    ThreadPool.QueueUserWorkItem(t =>
        {
            // enumerate recipientsToEmail and send email
        });
}

how to connect two people in your website

9 votes

There is a game called Verbosity (it's a Game With A Purpose) and it's on this link
www.gwap.com

in the game they connect two players randomly to play with each other, the game is that player1 should describe a word to his partner(player2) and player2 should gues the word.
I'm trying to build a website that do something like that, but I wonder
1- how I can connect two players randomly to let them play together although they are not registered users ( they are just guests to the website )?
2- how to make them playing in private game, i mean each two players are playing their own game?
3- What would I need to use? Is it enough to use ASP.Net? Do I need silverlight?
Thanks

In my understanding we have two logic entities:

Games: involve interactivity between two players in private

Players: Visitors (anonymous) of a web site

I will start with Players because it’s easier. A visitor lands on your site and there is a need to (uniquely) identify him. The easiest solution is a Guid that can be used as a session parameter or as a session cookie (my suggestion). Guid is not a nullable type so any Guid of 32 zeros will be our undefined Guid.

Having your GUIDed visitors, you need a key/value collection that will connect them to games.

Scenario 1: Each visitor can be a player for only one game at a time. A Dictionary<player, game> can do the job and visitors who are not players can easily be traced (game = undefined Guid)

Scenario 2: Each visitor can be a player for many games at the same time. A Dictionary<player, List<game>> is the solution but game = undefinedGuid will become List.Count = 0

Now let’s see what you can do with games. First of all you can use GUIDs to identify your games. This means that your players dictionary will be Dictionary<Guid, Guid> for scenario 1 or Dictionary<Guid, List<Guild>> for scenario 2. Obviously you will need a key/value collection for the games, let’s say in the form of Dictionary<gameGuid, gameDetails>. GameDetails must be a class holding the necessary information that can define the interactivity between the players. In other worlds this class must include the role of each player (role 1: the one who asks or role 2: the one who is guessing) and the messages they exchange as a key/value collection where key is the player Guid and value is a string message.

To summarize you will need two static dictionaries defined in your global.asax, one for the players and one for the games. You will also need a GameDetails class similar to this (basic concept implementation):

class GameDatails
{
  public Guid Role1 { get; set; } // holds the guid of the player who asks
  public Guid  Role2 { get; set; } // holds the guid of the player who guesses
  public List<KeyValuePair<Guid, string>> Messages; // holds the player/message pairs
  public GameDetails(Guid role1, Guid role2)
  {
    this.Role1 = role1;
    this.Role2 = role2;
    this.Message = new List<KeyValuePair<Guid, string>>();
  }
}

Adding and removing players is easy as well as games (players are connected to games).

There are a lot of other things you can do (ie the one who guesses quits and you randomly assign another player to continue etc).

More or less this is also the way to make an asp.net chat with private rooms. It may be helpful for you to find and check a good sample of a simple asp.net chat script, see the logic and the implementation and adapt them to the above. In addition you can extend the chat script to support private rooms and have two applications instead of one.

Needless to say that asp.net is more than enough for your project. What you have to take in account is that if you cannot control you application pool recycling you will also need a persistence layer otherwise you may loose your dictionaries.

If you need more help just let me know.

How to avoid custom/Server error in web site?

8 votes

I have asp.net web application located on server I want to avoid all custom and server error from my site.

For that I have used

<customErrors mode="RemoteOnly" defaultRedirect="~/ErrorPage/TryAgainLater.aspx">   <error redirect="~/ErrorPage/PageNotFound.aspx" statusCode="404"/> </customErrors>

Using above code will able avoid some issue. ie.

Suppose "http://Exaple.com/Careers.aspx" Page available in my site then

Case 1. http://Exaple.com/Careersss.aspx "It was working correct as per above rule".

Case 2. http://Exaple.com/!@##Careersss.aspx "Not working" Note : Here I add special character

Case 3: http://Exaple.com/Careersss.aspxxxx "Not working" Note : add character after ".aspx"

case 4: http://Exaple.com/Careersss.aspx/!@!@!@! "Not works design breaking here". Note : Add '/' with special character.

please help me when user get case 2,3,4 then they automatically redirected to error page.

Thanks In advance.

For above problem we have to change IIS Setting please refer :

http://www.braintrove.com/id/46/page/2#Configure-IIS-for-custom-error-pages

http://blogs.msdn.com/b/webtopics/archive/2008/05/28/iis-7-0-http-error-pages.aspx

Is this a bug? Float operation being treated as integer

8 votes

This operation returns a 0:

string value = “0.01”;
float convertedValue = float.Parse(value);
return (int)(convertedValue * 100.0f);

But this operation returns a 1:

string value = “0.01”;
float convertedValue = float.Parse(value) * 100.0f;
return (int)(convertedValue);

Because the convertedValue is a float, and it is in parenthesis *100f shouldn't it still be treated as float operation?

The difference between the two lies in the way the compiler optimizes floating point operations. Let me explain.

string value = "0.01";
float convertedValue = float.Parse(value);
return (int)(convertedValue * 100.0f);

In this example, the value is parsed into an 80-bit floating point number for use in the inner floating point dungeons of the computer. Then this is converted to a 32-bit float for storage in the convertedValue variable. This causes the value to be rounded to, seemingly, a number slightly less than 0.01. Then it is converted back to an 80-bit float and multiplied by 100, increasing the rounding error 100-fold. Then it is converted to an 32-bit int. This causes the float to be truncated, and since it is actually slightly less than 1, the int conversion returns 0.

string value = "0.01";
float convertedValue = float.Parse(value) * 100.0f;
return (int)(convertedValue);

In this example, the value is parsed into an 80-bit floating point number again. It is then multiplied by 100, before it is converted to a 32-bit float. This means that the rounding error is so small that when it is converted to a 32-bit float for storage in convertedValue, it rounds to exactly 1. Then when it is converted to an int, you get 1.

The main idea is that the computer uses high-precision floats for calculations, and then rounds the values whenever they are stored in a variable. The more assignments you have with floats, the more the rounding errors accumulate.

Using Enums with Code First & Entity Framework 5

8 votes

Just trying to confirm an impression: it seems enums in EF5 + Code First are only supported when declared within the same namespace as the classes using them as property types.

Can anyone confirm that? Couldn't find anything on the web for this...

A relevant bug that was fixed earlier. 4.3 Beta 1 release notes say:

Bug fix for GetDatabaseValues. In earlier releases this method would fail if your entity classes and context were in different namespaces. This issue is now fixed and the classes don’t need to be in the same namespace to use GetDatabaseValues.

My guess is that GetDatabaseValues function is still buggy for this occasion (but that's just an educated guess). You may want to report this here: ADO.NET team blog: EF5 Beta 1 Available

jquery autoComplete with List<string> as Source

7 votes

i have text box name txtEmailList, i provided autocomplete list for it,

 <asp:TextBox runat="server" ID="txtEmailList" CssClass="txtAutoComplete">

script for autocomplete

$('#txtEmailList').autocomplete({
                source: function(request, response) {
// this is the ajax call, which is running successfully
                    var msg = 
Assessments_JqueryAutoComplete.AutoComplete(request.term).value; //(ajaxpro functions)
                    response(msg.d); 
                }

            });

output will come as like this (in firebug it shows as plain/text), how can i attach this array to source property. ( i cant use $.ajax method, as i need to use ajaxpro as office rules), so i get the list of array back from ajax call, how do i bind the autocomplete.

["List 1","List 2","List 3","List 4"];/* // this is the output response from jquery( from firebug)

[AjaxPro.AjaxMethod(HttpSessionStateRequirement.ReadWrite)]
public List<string> AutoComplete(string query)
{
List<string> objLisItmes = new List<string>();
objLisItmes.Add("List 1");
objLisItmes.Add("List 2");
objLisItmes.Add("List 3");
objLisItmes.Add("List 4");
return  objLisItmes;
}

this is the firebug output in for Response headers

Cache-Controlno-cache Content-Length40 Content-Typetext/plain; charset=utf-8 DateWed, 07 Mar 2012 10:45:37 GMT Expires-1Pragmano-cache

Instead of returning a List. I would return a string Array as:

[AjaxPro.AjaxMethod(HttpSessionStateRequirement.ReadWrite)]
public string[] AutoComplete(string query)
{
   List<string> objLisItmes = new List<string>();
   objLisItmes.Add("List 1");
   objLisItmes.Add("List 2");
   objLisItmes.Add("List 3");
   objLisItmes.Add("List 4");
   return  objLisItmes.ToArray();
}

Get running session count from IIS for my hosted Asp.Net web site

7 votes

I am hosting an Asp.Net website in IIS 6.0

We have to reset the session timeout in web.config

My client want me to reset it only if no session is running (no one is using the site).

We have not used Membership and SessionState is set to InProc

Can I know if anybody using the site or any session is running for my application in IIS.

I can't make change in source code or any other file except web.config in the hosted website.

I'm not great at PowerShell, so hopefully you can look up the proper syntax. But ...

One option is to run a Powershell script and check the count of the session like this:

UPDATE: Changed 'Sessions Total' to 'Sessions Active'

write-host Getting performance counters ...

$perfCounterString = "\asp.net applications(__total__)\sessions active" 
$counter = get-counter -counter $perfCounterString 
$rawValue = $counter.CounterSamples[0].CookedValue 

write-host Session Count is $rawValue

if( $rawValue -gt 0)
{
   write-host Session are active - will not stop IIS
   exit
}

write-host Stopping IIS
stop-service "IISAdmin"

# Set values 
$webConfig = "d:\web.config"
$newTimeout = "20"

# Open file and change value
$doc = new-object System.Xml.XmlDocument
$doc.Load($webConfig)
$doc.SelectSingleNode("//sessionState").timeout = $newTimeout
$doc.Save($webConfig)

write-host Starting IIS
start-service "IISAdmin"
write-host Done!

Save this on the desktop as "ChangeIIS.ps1".

Now Powershell doesn't like you just running scripts like .bat files. You have to grant access to the process or your user for security reasons. So do the following:

  1. Open a command prompt and Run As Administrator
  2. Type powershell
  3. Type Set-ExecutionPolicy -scope process Bypass
  4. Type sl <path to directory of .sp1 file> . sl [set-location] is like cd in command prompt
  5. Type $ '.\ChangeIIS.ps1'

It will run now and reset the value.

Here is a link to my blog on how I created the PowerShell script in a more Step-by-step fashion

Disable Directory Listing in IIS

7 votes

In my web application all the .aspx pages resides in Pages directory. The project structure is shown below:

enter image description here

The Home.aspx is set as Start Page and the Web.config file of the Pages folder contains:

<configuration>
<location path="Secured">
    <system.web>
    <authorization>     
        <deny users="?"/>
        <allow users="*"/>
    </authorization>
    </system.web>
</location>
</configuration>

And the main Web.config has:

<authentication mode="Forms">
  <forms loginUrl="~/Pages/Login.aspx" timeout="2880" defaultUrl="~/Pages/Secured/Home.aspx" />
</authentication>

So when the application launches it redirects to the Login page with the URL:

http://localhost:2453/Pages/Login.aspx?ReturnUrl=%2fPages%2fSecured%2fHome.aspx

Now if I delete the

Login.aspx?ReturnUrl=%2fPages%2fSecured%2fHome.aspx

from that URL and press enter it is taking me to the Directory Listing:

enter image description here

What I want that it will again send me to the Login page located at

http://localhost:2453/Pages/Login.aspx

How can I achieve this? Your help be appreciated.

Thanks.

The localhost: enter image description here

You need to disable directory browsing from IIS or from the web.config

<configuration>
  <location path="Secured">
    <system.webServer>
      <directoryBrowse enabled="false" />
    </system.webServer>
  </location>
</configuration>

this entry above applies to IIS 7+, for IIS 6 you'll have to do it from IIS Manager

Is an ASP.net MVC View a "class"?

7 votes

...before everything, I'm doing this out of curiosity only. Nothing real-world application here, but just for knowledge and tinkering about...

ASP.NET Views have properties like Model and ViewData and even has methods as well.

You can even use @Using just like a regular class.cs file.

I know that it is of type WebPageView<TModel>

My main question is: is it a class?

It should be because it's a type, but..

I should be able to also do this then (Razor engine):

@{
   public class Person
   {
       //etc...
   }

   var p = new Person();
}

<span>@p.Name</span>

However I can't.. why?

note: currently a C#, ASP.net beginner.

You can't do it because Razor markup is compiled into a sequence of statements inside a method within the generated class derived from WebViewPage or WebViewPage<TModel>

The more important question though, is why would you want to do this? Instead prefer to keep Razor free of this kind of logic - it's job should be to produce layout, not do any kind of business logic, or business data transformation. Do all the heavy lifting in your action method and deliver a Model that describes the data required to render the layout in a format that requires only simple Razor markup to process.

There are quite a few tutorials a round that describe how to approach MVC and Razor. I dug up this one that is brief but does a reasonable job of covering an end-to-end story that might help you get the idea. It does include using EF to get data as well which might be more that you were bargaining for - but it's worth a read to get the full picture of how a whole architecture hangs together: http://weblogs.asp.net/shijuvarghese/archive/2011/01/06/developing-web-apps-using-asp-net-mvc-3-razor-and-ef-code-first-part-1.aspx

Allowing Simplified Chinese Input

6 votes

The company I work for is bidding on a project that will require our eCommerce solution to accept simplified Chinese input. After doing a bit of research, it seems that ASP.net makes globalization configuration easy:

<configuration>
  <system.web>
    <globalization
      fileEncoding="utf-8"
      requestEncoding="utf-8"
      responseEncoding="utf-8"
      culture="zh-Hans"
      uiCulture="en-us" />
  </system.web>
</configuration>

Questions:

  1. Is this really all there is to it in ASP.net? It seems to good to be true.
  2. Are there any DB considerations with SQL Server 2005? Will the DB accept the simplified Chinese without additional configuration?

Ad 1. The real question is, how far you want to go with Internationalization. Because i18n is not only allowing Unicode input. You need at least support local date, time and number formats, local collation (mostly related to sorting) and ensure that your application runs correctly on localized Operating Systems (unless you are developing Cloud aka hosted solution). You might want to read more on the topic here.

As far as support for Chinese character input goes, if you are going to offer software in China, you need to at least support GB18030-2000. To do just that, you need to use proper .Net Framework version - the one that supports Unicode 3.0. I believe it was supported since .Net Framework 2.0.
However, if you want to go one step further (which might be required for gaining competitive edge), you might want to support GB18030-2005. The only problem is, the full support for these characters (CJK Unified Ideographs Extension B) happened later (I am not really sure if it is Unicode 6.0 or Unicode 6.1) in the process. Therefore you might be forced to use the latest .Net Framework and still not be sure if it covers everything.
You might want to read Unicode FAQ on Han characters.

Ad 2. I strongly advice you not to use SQL Server 2005 with Chinese characters. The reason is, old SQL Server engine supports only UCS-2 rather than UTF-16. This might seems as slight difference, but that really poses the problem with 4-byte Han Ideographs. Actually, you want be able to use them in queries (i.e. LIKE or WHERE clauses) - you will receive all records. That's how it works. And to support them, you would need to set very specific Chinese collation, which will simply break support for other languages.
Basically, using SQL Server 2005 with Chinese Ideographs is a bad idea.

Why some asp.net developers encrypt ConnectionStrings?

5 votes


I seen some asp.net developers encrypt ConnectionStrings that was included in separate config file.
Why they did that ? I know that config files are unreadable from the client side/browser! Is it possible to access to this kind of files ?

You can't rule out that the web box is compromised. Also, you don't want the web admins to know passwords to databases.

ASP.net MVC View's Model vs ViewData.Model?

5 votes

I'm learning asp.net mvc and found something interesting:

It seems that I can't explicitly define a View's Model from within the View with error message saying that it has no setter.

@{ this.Model = "Hello" } //error

Then I looked at the source code in WebViewPage.cs and a View's Model property is actually like this:

public object Model { get { return ViewData.Model; } }

Thus the error.

But it's interesting how I can do this: @{ ViewData.Model = "hello"; } and actually be able to use the @model statement, resulting to "hello"

I think I'm looking too much into it, but why is this so?

beginner at C# and ASP.NET

The rule is Separation of Concern...In MVC, a Controller supplies a Model to a View and it will always be the controller that can set/assign a Model to a view....which the Views can use...this is by design...play by rules is what I would say...and If you are learning MVC its great and I would strongly recommend you to read

Stevens Sandersons MVC book

ajax jquery post, needs some fine tuning for a beginner

4 votes

i'm new to javascript and jquery and as part of a college project i need to make periodic checks the database to see if there has been changes. if there has been changes, i want the result of that change to 'alert' to the screen just to prove the AJAX call is working. i'm using asp.net and c#.

my scenario is: user 'A' logs in and sees user 'B' in a listbox populated by a global list. 'A' clicks on 'B' and clicks the play button. as this happens 'B's' invitedBy column in the User table in the DB changes to 'A'. this is where my problem is, i want to have a script that periodically accesses a web method in my UserDAO.cs class - which has a method that queries the invitedBy column in the DB (this has been tested and works). i'm having trouble getting this working, would someone take a look and see if they can spot anything. all help would be much appreciated!

DBPolling.js

    $(document).ready(function () {
function ajaxRequest() {
    $.ajax({
        type: "POST",
        url: "UserDAO.cs/queryInvitedBy",// is this correct way to input url?
        data: "{}",
        contentType: "application/json; charset=utf-8",
        dataType: "json",
        success: function (resultData) {
            //console.log(result);// i found this in an example...needed?
            if (resultData.status == 'pending') {
                setTimeout(function () { ajaxRequest(); }, 5000); // wait 5 seconds than call ajax request again
            } else {
                var result = eval(resultData);
                alert("You have been invited" + result);
            }
        }
    });
}

});

UserDAO.cs

[WebMethod]
    public string queryInvitedBy()
    {
        // New user
        User user;

        // Open the NHibernate session
        ISession session = NHibernateHttpModule.CurrentSession;

        IQuery q = session.CreateQuery(
            "FROM User WHERE InvitedBy IS NOT NULL");
            // Assign values to the ? placehoders, by their index (0,1, etc.)

        // Make sure List is not empty
        if (q.List<User>().Count > 0)
            // set user to first item in List
            user = q.List<User>()[0];
        else
            // set user to null if none found
            user = null;

        // If no users found, returned user will be blank, otherwise the valid user
        string result = user.InvitedBy.ToString();
        return result;
    }

i've been following online tutorials and looking at Qs similar to mine to get this far, so please let me know if i'm on the right track, or offer a solution if you see any problems.

Call your .aspx page, not the code behind.

url: "UserDAO.aspx/queryInvitedBy",