C#

...now browsing by category

 

The bad (might be good to some) attribute introduced in MVC4 – [InitializeSimpleMembership]

Thursday, August 21st, 2014

Yesterday I deployed a MVC4 app to Winhost and got this error below when I clicked on “Log In” or “Register”, which I didn’t when deployed to local IIS.

A network-related or instance-specific error occurred while establishing a connection to SQL Server. The server was not found or was not accessible. Verify that the instance name is correct and that SQL Server is configured to allow remote connections. (provider: SQL Network Interfaces, error: 26 - Error Locating Server/Instance Specified)

I had seen such error before; mostly the error was due to some misspelled SQL server name or firewall blocking remote access, etc. I checked my SQL server connection strings for both SqlClient and Entities Framework model and were able to connect to the remote SQL db hosted at Winhost. When I submitted a support ticket to Winhost tech team, their server side log showed that my app tried to connect to a SQL Express instance which they don’t support. How strange was that? I do not use SQL Express and my database which contains the ASP.Net Membership objects resides on a full version local SQL Server, not Express. There is no place in my web.config that has anything to do with SQL Express instance. So I examined the Controller codes where the Log In link is clicked; here it was, the new “InitializeSimpleMembership” attribute on the AccountController class which was created automatically by my selecting the “Internet Application” MVC4 project template. This was something new introduced by MVC4 team at Microsoft, where a bunch of genius are always trying to come up with some dummy robot codes to  make everything so automatic – by “simply” looking for a SQL Express db to initiate the Membership provider for Web.Security; this “InitializeSimpleMembership” attribute, as it turns out, was the only culprit for all these non-simple headaches when you deploy your site to hosting server that usually do not support SQL Express. And there was no warning or error when I used the Publishing wizard from VS2012 to deploy the site to Winhost.

The fix? Simply commented out the attribute, as shown below,and re-deployed to Winhost; then everything works!

[Authorize]

  //[InitializeSimpleMembership]
    public class AccountController : Controller
    {
        //
        // GET: /Account/Login

        [AllowAnonymous]
        public ActionResult Login(string returnUrl)
        {
            ViewBag.ReturnUrl = returnUrl;
            return View();

ASP.NET Web service call error, “Unable to generate a temporary class (result=1)”

Tuesday, February 19th, 2013

Got this obscure error while calling a web service method that requires a Xml serializer:

Unable to generate a temporary class (result=1).\r\nerror CS2001: Source file ‘C:\\Windows\\TEMP\\qdrb02m1.0.cs’ could not be found\r\nerror CS2008: No inputs specified\r\n”}  System.Exception {System.InvalidOperationException} “

 

Web searches on key phrase “Unable to generate a temporary class (result=1)” returned some useful results but none could directly resolve my issue. But general direction was pointing to the proper permission of the ASP.Net surrogate identity that most likely does not have sufficient right to the local I/O where XML serialization takes place.

To prove this, I fired up a console application and called the same web service method; as anticipated, the Console app did not throw error at all. So that’s true – it is to do with the Windows account that IIS uses to run the ASP.Net process.

By default, IIS7 uses “ApplicationPoolIdentity” as the Identity for the Application pool automatically created when a new website is added to the IIS/Sites. But what’s underneath this mysterious “ApplicationPoolIdentity” – you could not even find it in Windows by looking up user accounts? Below are several things I tried and let’s see how they fared:

  1. I tried to give “Full Control” permission to ASP.NET Machine Account on c:\windows\Temp folder. Not work.
  2. Changed the app pool identity to “Network Service” (via IIS7/Site/Advanced Settings) and gave the “Network Service” full control permission to c:\windows\temp (via Windows Explorer). It worked! Then I reduced permission to only “Read, List Folder Contents”, and it still worked.
  3. Changed the app pool identity to “Local System”, of course that worked too.

 

So, at the end, to get rid of error “Unable to generate a temporary class (result=1)..”,  I ended up using the “Network Service” as the Application Pool identity (leave the security mode as Integrated) and granted the “Network Service” account permission “Read, List folder contents” on “C:\Windows\Temp” folder.

P.S.: after I deployed the web app to my staging web server, the error returned. The staging server is running IIS6 and the app pool identity by default was already tied to “Network Service” account. So I went directly to the c:\windows\temp folder and as I anticipated, the account did not have “read, list folder contents” permission. So I granted the permission to “Network Service” account and then it all worked!

Asp.Net Form Postback error:Error – Operation is not valid due to the current state of the object

Wednesday, December 12th, 2012

Sometimes when there are a large number of input fields on a Asp.Net form, and doing postback, I would get this error:
“Error – Operation is not valid due to the current state of the object”

As it turned out there is a restriction on how many fields can be posted back to server and the large grid that contains a large number of textbox fields probably was the culprit. Google search returned some postings that all point to the configure setting

<appSettings>
<add key=”aspnet:MaxHttpCollectionKeys” value=”2000″ />
</appSettings>

 

After I stuck this line into the appSettings, the problem went away.

Smtp Permission error at Winhost

Friday, December 7th, 2012

When I was developing my ASP.Net app on local machine,  I had no problem sending email by calling directly the SMTP relay server assigned by my hosting company Winhost, with port set to 587 of course. But when I deployed the app to the winhost server, the email tool threw this exception :

Request for the permission of type ‘System.Net.Mail.SmtpPermission, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089′ failed.

I did suspect some some security permission to Smtp related assembly and have done some search toward that direction. First I got a lead from some post via Google search and one suggested added this entry into the <system.web> section; but that did not work, so I am not going to give reference to this post.

<securityPolicy>
<trustLevel name=”Full” policyFile=”internal”/>
</securityPolicy>

Today, I went into Windost support site and did another search on their forum, and they pointed me to using this instead:

<system.web>

<trust level=”Full” />

</system.web>

Yes, that was all it needed!

Setting up Elmah SQL Server objects manually

Tuesday, 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

Thursday, 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!

Allow other machine to connect to WCF Service hosted on localhost, Win7/IIS7

Thursday, November 10th, 2011

Moving along with my WCF project; today I needed to connect to the WCF services developed and published to my development machine (localhost, let’s mask its name as “dev1″) from another machine, named “user1″,  in the same network domain, and got the “Operation timed out” error 118. My localhost machine is a Windows 7 Enterprise and the WCF services are hosted on IIS7. Obviously, this was a security setting on the firewall on local machine that had blocked remote access.  Below are the steps I went through to get the problem resolved:

  1. First, I checked if I had access to default port, 80 at dev1 from user1 before I did anything; I browsed to http://dev1/Defaultsite/Default.aspx, and fair enough, not a chance – page was not rendering.
  2. On localhost (dev1), I went to Control Panel -> System and Security -> Windows Firewall -> Allowed Programs; highlighted “World Wide Web Services (HTTP) and changed settings -> checked “Domain” and “Home/Work (private)” checkboxes.
  3. Now browsed to http://dev1/Defaultsite/Default.aspx again and it worked!
  4. But when I browsed to a different port at dev1, http://dev1:8088/WcfHost/Service1.svc, I got denied again, error 118, “The operation timed out”, scary..I thought that I might need to turn on Windows Communication Foundation allowed programs inside Windows Firewall; so I did that but then it sill not worked.
  5. Is this WCF issue or port opening issue? To test that, I created a plain website, TestWeb, and hosted at http://dev1:8088/Testweb, and it still cannot be accessed from “user1″ machine. So this must be that port 8088 is not accessible from another machine.
  6. Back to Windows firewall config tool and went to Advanced Security Settings and created a new inbound connection rule, “RemoteAccessToPort8088″ to allow remote connection to port 8088 and 444.
  7. And this did it! Now I was able to access both http://dev1:8088/WcfHost/Service1.svc and https://dev1:444/WcfHost/Service1.svc from “user1″ machine.

Create and apply a self-signed certificate – Windows 7/IIS7

Sunday, August 7th, 2011

Creating a self-signed certificate on Windows 7/IIS7 was quite a different experience and it took me more time to set it up and work correctly (in retrospect, it should have been easier as most of things can be configured with GUI tool). Anyway, I don’t want to repeat the pain and relearn how this is done, let me summarize the steps here to share with others and to help me find it easier in a rainy day:

  1. Open IIS7 (If IIS7 is not available from Administrative tools, go to Control Panel – > Programs – > Turn Windows Features On or Off.
  2. Click on machine node then double click on “Server Certificates” on the IIS pane
  3. Select “Create self-signed certificate” from the “Action” pane and give a friendly name such as “WcfSecure” in this case.
  4. Once the server certificate is created, view the certificate detail and write down the Thumbprint, something like ae 8f b2 b4 b0 b6 07 16 8e 73 51 35 38 cd 6b bb 7e 1f 12 d5, and remove the spaces to become ae8fb2b4b0b607168e73513538cd6bbb7e1f12d5, copy it to notepad for later use.
  5. Next, configured the Certificate to port, using VS2010 Guid tool to generate a GUID and run VS2010 Command prompt (must run as admin):netsh http add sslcert ipport=0.0.0.0:8080 certhash=ae8fb2b4b0b607168e73513538cd6bbb7e1f12d5 appid={0270078A-39C3-47E8-845C-07D904672C71}
  6. Created a website to use the certificate so that WCF Service can be hosted in https mode; to do that click on Sites node and right click ->Add Web Site ->Named it “WcfDemo” and assign to Port 444 (443 and 442 have already been taken)
  7. Assign the certificate to the new website by choosing Binding type “https”, and pick the certificate from the Certificate drop down; certificate is on machine or server level, so there could be multiple certificates and multiple site can use same certificate.
  8. Refer to MSDN article at http://msdn.microsoft.com/library/ff406125.aspx for more in-depth detail.

It is important to note, that In IIS7, whenever a new website is created, it automatically creates a new application pool named the same as website, in this case, WcfDemo is the new app pool. And it automatically defaulted to use .Net Framework version 2.0, so be careful to manaully change it to the version that your Wcf app is using, in my case, changed to .net 4.0. Pay attention to Identity; by default, the Identity uses ApplicationPoolIdentity, other options are LocalService, LocalSystem, NetworkService, these are under Built-in account dropdown; you can also use Custom account and use the Windows user account for the application pool identity. If sqlexpress database is used for storing Membership users and if the security mode is set to use Integrated Security=true, then the
Application pool identity must use Localsystem or an “An unsecured or incorrectly secured fault was received from the other party. See the inner FaultException for the fault code and detail.” error will throw when WCF client calls the Wcf Service from this website.

If, however, the sql database uses “SQL Server Authentication” mode and passes in a predefined username and password in the sql connection string, then you can leave the default ApplicationPoolIdentity alone.

Display Windows Message Box from Console App

Tuesday, July 27th, 2010

In a Console app, you normally write out message to screen using Console.WriteLine(). How should I display a Windows message box like we usually do in a Windows Form app?

Call the MessageBox method from user32.dll COM API is one of the methods I learned, and here were how it was done (no need to set reference to user32.dll; just do DllImport):

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Runtime.InteropServices;

 

namespace ComInterop

{

class Message

{

 

public static void ShowMessage(string msg,string caption)

{

 

//MessageBox(new IntPtr(0), msg, caption, 0); //type=0 only show OK button

MsgBox(new IntPtr(0), msg, caption, 1); //Type=1 shows both OK and Cancel button

 

 

}

[DllImport(“user32.dll”)]

private static extern int MessageBox(IntPtr hwnd, String text, String caption, uint type);

//if want to use different method name other than what’s given in the type lib, use EntryPoint attribute

[DllImport(“user32.dll”, EntryPoint = “MessageBox”)]

private static extern int MsgBox(IntPtr hwnd, String text, String caption, uint type);

}

 

class Program

{

static void Main(string[] args)

{

//user32.dll DLLImport

Message.ShowMessage(“This method used DllImport”, “DllImport is Cool”);

}

}

 

}

 

Playing with sapi.dll

Tuesday, July 27th, 2010

With Microsoft’s Speech Library, it is extremely easy to add voice to your .Net application.

I created a small Console app in VS2010 and here were the steps I took:

  1. Add reference to sapi.dll, which was found in my computer’s C:\Program Files\Common Files\Microsoft Shared\Speech (Windows XP SP2)
  2. Import the Speech type library namespace
  3. Instantiated a SpVoice and called the Speak method; that was all.
Sample codes:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using SpeechLib;
namespace ComInterop
{
class Speech
{
public static void SayThis(string words)
{
SpVoice voice = new SpVoice();
voice.Speak(words, SpeechVoiceSpeakFlags.SVSFDefault);
}
}
static void Main(string[] args)
{
////speech library
Console.WriteLine(“Type a few words to speak”);
string words = Console.ReadLine();
Speech.SayThis(words);
Console.ReadKey();
}
}