Setting up Elmah SQL Server objects manually

Written by stevey on December 4th, 2012

1. Run Elmah.axd on localhost and got this error,”Could not find stored procedure ‘ELMAH_GetErrorsXml'”.
What happened was that the Elmah sql objects were not installed properly when I run NuGet package-install elmah from inside VS2010 IDE.

2. Remedy was downloading the elmah-1.2-db-sqlserever.sql script from here
4. Open SQL Server 2008 Management studio and connected to the remote database hosted at Winhost
5. Opened the Elmah db sql script file and executed it on the remote database.
6. Now returned to localhost/Elmah.axd and error log is showing.

 

Open a new window from aspnet code-behind

Written by stevey on November 29th, 2012

While creating a Cmi course launch Simulator, I run into the need to open up a new window from asp.net code behide, instead of simply doing a Response.Redirect, which will just transfer the browser window to the target AU entry window, and the window where Cmi Simulator launched the course will be lost.

After reading posts here and there, I learned there were three possible ways to achieve what I needed and I picked the one that best suit me to implement in the end solution.

Soution 1: Simply open a new tab to display AU Entry page

On the CmiSimulator.aspx, I had a server-side button called btnLaunchCourse, when the button is clicked, it simply grabs the

LaunchUrl on the page and does a response.Redirect to the website and page defined in the LaunchUrl. To make sure the target page is displayed in a different tab on the browser, just added the OnClickClick attribute like below:

Text=”Launch Course” CssClass=”submitButton” OnClientClick=”form1.target=’_blank';” />

The code-behind OnLaunchCourse has only this line of code:

Response.Redirect(LaunchUrl);

Here Form1 is the id of the aspnet form on the page. If the page is embedded in a master page, the form tag is located in the master page.

Solution 2: Open a pop-up window

Keep the button html code as it is,

Text=”Launch Course” CssClass=”submitButton” />

And register javascript to open a new window from code-behind “OnLaunchCourse”:

protected void OnLaunchCourse(object sender, EventArgs e)
{

//Response.Redirect(txtLaunchUrl.Text);
string url = txtLaunchUrl.Text;
string newWindow = “window.open(‘” + url + “‘,’_blank’,’height=700,width=800,status=yes, toolbar=no, menubar=no,location=no,scrollbar=yes, resizable=yes, titlebar=no’);”;
ScriptManager.RegisterStartupScript(this, typeof(string), “OpenWindow”, newWindow, true);

}

Solution 3: Extension method

public static void Redirect(this HttpResponse response, string url, string target, string windowFeatures)
{
//credit to this posting at http://stackoverflow.com/questions/104601/asp-net-response-redirect-to-new-window

//windowFeatures example:

windowFeatures=”directories=no,toolbar=no,menubar=no,location=yes,status=no,resizable=yes,width=800,height=600″;
if ((String.IsNullOrEmpty(target) || target.Equals(“_self”, StringComparison.OrdinalIgnoreCase)) &&

String.IsNullOrEmpty(windowFeatures))
{
response.Redirect(url);
}
else
{
Page page = (Page)HttpContext.Current.Handler;

if (page == null)
{
throw new InvalidOperationException(“Cannot redirect to new window outside Page context.”);
}
url = page.ResolveClientUrl(url);

string script;
if (!String.IsNullOrEmpty(windowFeatures))
{
script = @”window.open(“”{0}””, “”{1}””, “”{2}””);”;

}
else
{
script = @”window.open(“”{0}””, “”{1}””);”;
}
script = String.Format(script, url, target, windowFeatures);
ScriptManager.RegisterStartupScript(page, typeof(Page), “Redirect”, script, true);
}
}

At the end, the most elegant solution is the extension method and that was implemented in my final solution. I thank the author of this extension method, Tančev Saša, you’re my hero of the day!

 

Add a website to local IIS7 and browse to it with friendly name

Written by stevey on October 2nd, 2012
  1. Launched IIS7 -> Sites -> Add Web Site
  2. Entered yangsoft.com; left application pool with default name
  3. Mapped to physical path H:\Development\yangsoft.com\Yangsoft.Web
  4. Pick a unassigned port: 8092
  5. Host name: yangsoft.com (hopefully, this will precede the real domain name, once the entry is made into hosts file)
  6. After exiting IIS7, browsed to C:\Windows\System32\drivers\etc and opened the hosts file with notepad
  7. Added this entry: 127.0.0.1 yangsoft.com and saved.
  8. Browsed to http://localhost:8092 but get a bad request error 400: invalid hostname
  9. Returned to IIS7 and changed App Pool Identity “yangsoft.com” to use .net 4.0 and Integrated Mode. By default, whenever a website was first setup, it uses .net v 2.0
  10. Now go to browser and type in :yangsoft.com:8092 and it brought up the local site that is in development folder, not in the deployed folder.
  11. In order to launch the website from VS 2010 IDE in the same fashion, I went into VS2010 web project properties and changed the Servers setting from “Use Visual Studio Development Server” to “Use Local ISI Web server” and pasted in the url: yangsoft.com:8092
  12. Ran the project in debug mode and now the website rendered as http://yangsoft.com:8092/Default.aspx instead of the http://localhost:2236/Default.aspx or whatever random port number the IDE picks for you.
 

Do not use VS2005 to edit .Net 1.1 aspx file

Written by stevey on September 28th, 2012

Today, I learned another painful lesson using Visual Studio 2005 to edit a live ASP.Net 1.1 page (.aspx file) – after I made some minor change on html codes and saved it back , the whole site blew up. What happened was that VS2005 automatically inserted a few .net 2.0 assemblies into the web.config file on the live server, even I just pull down a file to local machine and used my VS2005 to edit it.

These are those assemblies that were added by VS2005:

<add assembly=”System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=B03F5F7F11D50A3A”/>
<add assembly=”System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089″/>
<add assembly=”System.Configuration, Version=2.0.0.0, Culture=neutral, PublicKeyToken=B03F5F7F11D50A3A”/>
<add assembly=”System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=B03F5F7F11D50A3A”/>
<add assembly=”System.Xml, Version=2.0.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089″/>

Previously I used either VS2003, notepad or VS2008/2010 to edit the same page and never encountered something like this. So this must be some VS2005 specific bug and Microsoft probably realized that it did too much automation in VS2005 and fixed that in later versions of VS.

So never edit a .net 1.1 ASP.Net webpage inside VS2005.  It is fine to use VS2003, VS2008 or VS2010, though.

 

One glitch to watch for while migrating jQuery lib from 1.3.2 to 1.7.1

Written by stevey on September 14th, 2012

A recent deployment of my production website involved upgrading jquery library from jquery-1.3.2.min.js to jquery-1.7.1.min.js. Everything seemed to be fine except one place that was out of place – a customized div message box that initially displayed correctly next to mouse pointer now moved to the upper left corner of the screen.

What happened was that somehow 1.7.1 no longer supports $().mousemove() without passing in a definitive element identifier in the $(). Before the upgrade (jquery1.3.2.min.js), I used this code to capture the mouse position:

 var mouseX; var mouseY; $().mousemove(function(e){ mouseX=e.pageX; mouseY=e.pageY; }); 

And the mouseX and mouseY would have legit values. But these values were lost when I upgraded to jquery.1.7.1.min.js, if I kept the same code.

As it turned out, I needed to put a definitive html element id, either an id for a div or a table, in the $(). The new code that works the same as before the upgrade now should look like this:

var mouseX;
var mouseY;
$("#divid1").mousemove(function(e)
{
mouseX=e.pageX;
mouseY=e.pageY;

});

Now my popup box would display correctly to where I have my mouse over some item with this code below:


function showHints(msgDivId, msg,visible)
{
//alert("mouse position: " + mouseX + "," + mouseY);
var ch=$("#" + msgDivId);
ch.html(msg);
ch.addClass('hoverPopup');
ch.css({
left:mouseX+10,
top:mouseY-10
});
if (visible && msg.length>0)
ch.show();
else
ch.hide();

}

 

Adding the specified count to the semaphore would cause it to exceed its maximum count.

Written by stevey on June 27th, 2012

This was a scary error message I got it today while I tried to switch my EF project to connect to a live database. The way I did the switch was have a pair of Entity Framework connection strings in my web.config, with one pointing to development and one to production database, and when the switch turned to production, the system will automatically pick up the live connection string; and that’s it. Test had been going well in development environment and the production database was exact copy, in terms of schema, of the developmental one, so I felt confident to make the switch and expected the codes should run as expected.

But then came this ugly and convoluted error message from the bottom of Entity framework, “Adding the specified count to the semaphore would cause it to exceed its maximum count.”; what on the earth was this? Google search for the phrase returned quite a few answers, some suggesting it might be sql queries had error, other pointing to Microsoft internal bug in db connection pooling. I found this one clicked – disabling pooling; I always favor simple than complex; this was simplest to do, just added an entry to my connection string, which by default was enabling connection pooling. Amazingly, that did it and the error went away! So here was the EF connection string before I made the change, connectionString=”metadata=res://*/MyModel.csdl|res://*/MyModel.ssdl|res://*/MyModel.msl;provider=System.Data.SqlClient;provider connection string=&quot;data source=sqlSvr1;initial catalog=sqlDb1;integrated security=false;user id=user1;password=password1234!;multipleactiveresultsets=True;App=EntityFramework&quot;”

and here is the connection string that cleared the semaphore error,  connectionString=”metadata=res://*/MyModel.csdl|res://*/MyModel.ssdl|res://*/MyModel.msl;provider=System.Data.SqlClient;provider connection string=&quot;data source=sqlSvr1;initial catalog=sqlDb1;integrated security=false;user id=user1;password=password1234!;pooling=false;multipleactiveresultsets=True;App=EntityFramework&quot;”

More interestingly, after the error went away, I took out the pooling=false, and ran the app again, things just flied without anymore problem; I also switched back to development database, with pooling option enabled, and still didn’t see the semaphore error as I expected that I would. So, if I could regenerate the error at some point, I suspect if I just simply clean the solution and rebuild the entire solution, I might achieve the same outcome – no more this dreadful and convoluted error, “Adding the specified count to the semaphore would cause it to exceed its maximum count.” (got it from the InnerException)


 

Inject custom message to warn user from closing browser window

Written by stevey on June 26th, 2012

In a recent project, I needed to inject a custom message to warn user not to simply close a browser window; they might be doing some online course work and have not sent their course data back to server, and accidentally close down the browser. We didn’t want that to happen. At the beginning, I attempted the window.unload() event, and placed custom message there; but that, strangely, only works in IE7, but not in IE8,9, or recent versions of Chrome.

Naturally, I resolved to jQuery and found that this posting here at http://www.mkyong.com/jquery/how-to-stop-a-page-from-exit-or-unload-with-jquery/ was most useful. The author of this posting gave a good example and even embedded a demo. The thing I wanted to stress is that you must place the javascript code that handles the “beforeunload” event inside the body tag. At first, I placed in in <head> section and the event handler did not fire.

For jQuary library, I used direct reference from Google hosted solution, instead of referencing to local resource. Click hereto see what it looks like with different browsers and view the source. Try to enter a custom message to the text box on the lower part of the page, then try to close your browser. You will see the message you type in the box get added to the browser’s warning message while you try to close the page. For FireFox, it behaves quite differently – the custom message never got displayed and the default message differs from IE and Chorme, as shown in the image.

 

MvcCheckBoxList for MVC3

Written by stevey on May 31st, 2012

As of today, there is not existing Html exentension for CheckBoxList. You can find @Html.CheckBoxFor but you don’t see @Html.CheckBoxListFor<>, untill, you download and install third party dll or build your own. Today I found one that you can get from NuGet, by reading up article at CodeProject http://www.codeproject.com/Articles/292050/MVC3-Html-CheckBoxList-custom-extension

MVC3 @Html.CheckBoxList extension isntalled from NuGet:

PM> install-package MvcCheckBoxList
Successfully installed ‘MvcCheckBoxList 1.4.2.3′.
Successfully added ‘MvcCheckBoxList 1.4.2.3′ to ETEF.Web.

 

Once MvcCheckBoxList was intalled, it shows up in the project reference as “MvcCheckBoxList”, no particular namespace.
How to use it?

On view:
<div>
<div>
<h3>Roles</h3>
@{
var roles = Model.AvailableRoles.Select(r=>new SelectListItem{Value=r.RoleName,Text=r.RoleName}).ToList();

}

@Html.CheckBoxList(“roles”,roles)
</div>
</div>

on controller:

how to intercept the checkboxes that are selected?
After user clicks on Submit button, the checked boxes were posted as an array of strings. Example in my ETEF.Web WeblinkController code:

[HttpPost]
public ActionResult EditLink(WeblinkModel model, string[] roles)
{

using (ETEF.Data.Repositories.AccessControlRepository acr = new Data.Repositories.AccessControlRepository(GlobalSettings.Database.EntitiesConnectionString))
{
Weblink lnk = new Weblink();
lnk.LinkID = model.WebLinkID;
lnk.LinkText = model.LinkCaption;
lnk.LinkTypeID = model.LinkTypeID;
lnk.NavigateUrl = model.NavigateUrl;
lnk.Roles = GlobalFunctions.ConverArrayToString(roles);
lnk.StatusID = 1;
lnk.DisplayOrder = model.DisplayOrder;
lnk.Description = model.Description;
//lnk.ImageUrl = model.ImageUrl;
int ret = acr.SaveWeblink(lnk);
if (ret > 0)
model.Message = DisplayMessage(“Success”, “Form data has been saved successfully.”, MessageBoxTypes.Success);
else
model.Message = DisplayMessage(“Problem”, “Form data was not saved successfully. Please check your input and try it again.”, MessageBoxTypes.Error);

if (model.WeblinkTypes == null)
{
model.WeblinkTypes = acr.GetWeblinkTypes();
model.AvailableRoles = acr.GetAvailableRoles();

}

}
return View(model);

}

 

Use reflection to retrieve SOAP Web service methods

Written by stevey on February 28th, 2012

For a local object, retrieving its public methods is quite straightforward using Reflection. Sample codes below will suffice:

using System.Reflection;
using ....;
MethodInfo[] methods = typeof(LocalObjectType).GetMethods(BindingFlags.Public | BindingFlags.Static);
//sort by method names
Array.Sort(methods, delegate(MethodInfo m1, MethodInfo m2)
{ return m1.Name.CompareTo(m2.Name); });
foreach (MethodInfo mi in methods)
{ Console.WriteLine(mi.Name); }

But this does not work if my type is a proxy type to a remote web service. After some readings here and there, I finally was able to get a list of web service SOAP methods from a SOAP ASMX url. Here are the function I created to return a List of the MethodInfo:

using System; using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using System.Net;
using System.IO;
using System.Web.Services;
using System.Web.Services.Description;
using System.CodeDom;
using System.CodeDom.Compiler;


public List<MethodInfo> GetSoapMethods()
{
System.Net.WebClient client = new System.Net.WebClient(); string asmxUrl = "http://myservices.mydomain.com/Service.asmx";
if (!asmxUrl.Contains("?wsdl"))
asmxUrl += "?wsdl";
System.IO.Stream stream = client.OpenRead(asmxUrl);
//read service description
ServiceDescription desc = ServiceDescription.Read(stream);
//initialize a service description importer
ServiceDescriptionImporter importer = new ServiceDescriptionImporter();
importer.ProtocolName = "Soap12";
importer.AddServiceDescription(desc, null, null);
//generate a proxy client
importer.Style = ServiceDescriptionImportStyle.Client;
importer.CodeGenerationOptions = System.Xml.Serialization.CodeGenerationOptions.GenerateProperties;
CodeNamespace nmspace = new CodeNamespace();
CodeCompileUnit unit1 = new CodeCompileUnit();
unit1.Namespaces.Add(nmspace);
//import the service into the code-dom tree, this creates proxy codes that use the service
ServiceDescriptionImportWarnings warning = importer.Import(nmspace, unit1);
if (warning == 0)
{
//System.Xml.Serialization.XmlSchemas mySchema = importer.Schemas;
//Console.WriteLine(mySchema.ToString());
//generate the proxy code
CodeDomProvider provider1 = CodeDomProvider.CreateProvider("CSharp");
//compile the assembly proxy with the appropriate references
string[] assemblyReferences = new string[5]{"System.dll","System.Web.Services.dll",
"System.Web.dll","System.Xml.dll","System.Data.dll"};
CompilerParameters parms = new CompilerParameters(assemblyReferences);
CompilerResults results = provider1.CompileAssemblyFromDom(parms, unit1);
Type[] types = results.CompiledAssembly.GetTypes();
Type foundType = null;
foreach (Type t in types)
{
if (t.BaseType == typeof(System.Web.Services.Protocols.SoapHttpClientProtocol))
{
Console.WriteLine(t.ToString());
foundType = t;
break;
}
}
//instantiate proxy class
object service = results.CompiledAssembly.CreateInstance(foundType.ToString());
//this will get all the methods, public or not in the webservice
List<MethodInfo> lstMethods = service.GetType().GetMethods().ToList();
return lstMethods;
}
else
{
Console.WriteLine("Warning..");
return null;
}
}

 

Installed WordPresss to Local IIS7

Written by stevey on February 13th, 2012

Before my memory evaporates again, let’s write down the steps on how this was done:

  1. Downloaded and Installed MySql database engine, then the Workbench (acts like SQL Server Management Studio). No need to write down the version; you will always to go their site to get the latest.
  2. I already installed PHP engine the other day so no need to redo it; this time around, just go to WordPress site http://www.wordpress.org and grabbed the latest .zip file, expanded to D:\Download\Wordpress
  3. Went to IIS7 Manager and added a new site, called “wordpress” and set the physical path to d:\download\wordpress, let the site use default ApplicationPool Identity, wordpress; and set binding to port 8089 and host name “blog.yang.com”.
  4. Before I could browse to http://blog.yang.com:8089, I needed to update the local host file; to do so, browsed to c:\windows\system32\drivers\etc\hosts. The file was not editable by default; so I opened the file property and gave myself  full control permission, changed the entry there from 127.0.0.1 blog.yangsoft.com to blog.yang.com; if the entry is not there, just add one.
  5. Before I could run wp install, I needed to create a database on local mysql server. I launched MySQL WorkBench 5.2 CE ->Server Administration ->File -> New Model. Once I clicked on New Model from File menu, it automatically created a MyDB, clicked on Edit schema and changed name to myblog, selecting collation to be UTF8-UTF8_General_CI.
  6. Added a mysql user account and gave it full db rights.
  7. It is almost there. Now I went to d:\download\wordpress and opened wp-config-sample.php, replaced DB related settings to point to localhost, db name “myblog” and the newly created username. Now I was ready to run WP install, the famous 5 minutes no-brainer!
  8. Went to IIS7, browsed to wordpress/wp-admin/install.php, and it was truly amazing it did only take about 5 minutes to get the site up and running!