Q If I establish a Web connection using HttpWebRequest and then read data from HttpWebResponse.GetResponseStream, I know it will fail if the Internet connection is lost, but do I need to be concerned about data packets being lost if the reading of data from HttpWebResponse.GetResponseStream finished without error? Does the underlying transport/protocol take care of retrying lost data packet and other problems?
A Yes, HTTP is built on TCP/IP, which handles all of the retries and data integrity for you. That said, there are a variety of ways this could legally fail to deliver the file. For instance, if the server is using HTTP 1.0 and uses a "Content-Close" header instead of a "Content-Length" header, the socket could be closed before the file was completely sent. The HttpWebRequest object won't throw an error because the server said "I'll close this when I'm done," and the connection had been closed, so the operation was entirely legal.
Q How can I run an application under specific credentials on the server side of an ASP.NET application? I tried the runas command, but it requires the user to key in the password at run time.
A If you're using Windows Server™ 2003 with IIS 6.0, you can create a new application pool in IIS with different credentials, and then set the virtual directory for your ASP.NET application to use that application pool. Here are the steps you should follow:
- Right-click Application Pool folder, select New.
- Walk through the wizard.
- After the application pool has been created, right-click it and then select Properties.
- Click the Identity tab and change the account.
- Assign the app pool to an application by right-clicking the folder in IIS and selecting Properties.
- Click the Directory/Home Directory Tab, change the AppPool dropdown to the application pool you created. The application will now run under the new application pool as the identity that you specified.
If you are using IIS 5.0, you can use impersonation in the Web.config to run the application as a specific user:
<identity impersonate="true" userName="domain\user" password="<pass>" />You could then use aspnet_setreg.exe to encrypt the username and password and put them in the registry, as you can read in Knowledge Base article 329290 ("How To Use the ASP.NET Utility to Encrypt Credentials and Session State Connection Strings"). You can also programmatically impersonate a user using the LogonUser function exported from advapi32.dll. For an example of how to do that in your ASP.NET application, see Knowledge Base article 306158 ("How To Implement Impersonation in an ASP.NET Application"), particularly the section on impersonating a specific user in code.
In IIS 5.0, if you want to run all applications as a specific user, you can change the userName and Password attributes of the <processModel> tag in the machine.config.
Q I am creating a DataGrid on a form and on page load I'm populating it by dynamically building template columns using a stored procedure. Everything works fine and I get the DataGrid. Now I am writing an update method which is the handler for the update button click. As soon as I enter this method, the value of DataGrid1.Items.Count becomes 0 and the DataSet says that the referenced object has a value of nothing. Why is the DataGrid emptied on a postback?
A The DataGrid control does not persist dynamically added columns across posts. If you decide that you want to add columns on the fly, you will have to recreate them each time the page is loaded and then rebind to the data source.
Q I am using data binding with a DataGrid. How can I get the index of a particular row in the DataTable's row collection?
A The Microsoft® .NET Framework 2.0 will have a property called IndexOf on DataRowCollection which gives the index of the row in the DataTable, as shown here:
dt.Rows.IndexOf(row);The IndexOf function exposed in the .NET Framework 2.0 performs well even for very large DataSets. However, if you're using the .NET Framework 1.x, then you'll have to resort to getting the index by brute force logic: Loop through all the rows in the row collection and find the row in the table which matches your row.
public int GetIndex(DataRow findRow) {
for (int i = 0; i < _dt.Rows.Count; i++) {
DataRow row = _dt.Rows[i];
if (row == findRow) {
return i;
}
}
return -1;
}
Be careful not to call the brute force function too often in your code, especially for larger DataSets, because of the performance implications of looping through all the rows in the table.
Q I am implementing a custom ADO.NET provider and so I would like to know which of the well-known ADO.NET interfaces is responsible for returning the list of tables and views in the underlying data store?
A In the ADO.NET 2.0 API, there are metadata discovery APIs. You can start with Connection.GetSchema. Unfortunately, in the .NET Framework 1.x, ADO.NET didn't include support for that in providers. If you choose to invent something to expose this functionality, you may want to stay in line with the ADO.NET 2.0 API so that you have a smooth upgrade path in the future. In the .NET Framework 2.0, you can use the new GetSchema methods. For more information on this, you can take a look at ADO.NET 2.0 new GetSchema method.
For the .NET Framework 1.x, you can use the native OLE DB schema information with GetOledbSchemaTable, so if you are using the System.Data.OleDb ADO.NET classes, try the technique described at Retrieving database independent schema information.
Q How can I know when to use available data providers versus developing database-agnostic data access?
A There are some great articles comparing when you can use each data provider and how you can develop database agnostic data access. For example, you should take a look at ".NET Framework Data Providers" along with "INFO: Roadmap for .NET Data Providers".
That document explains that Data Access Objects (DAO) and the Jet database engine minimize the differences between database systems so that you can port an application from one database to another with very few changes. With RDO and ADO you don't have the Jet intermediary, so you get better performance and more server-specific functionality. However, this can make it harder to port an application between databases.
ADO.NET provides better performance but it includes separate classes for each .NET data provider. You can, however, use standard interfaces and isolate initialization code into "factory" functions so that you change less code. Plus, the DataSet object represents a central object for data binding and remoting that is independent of the data provider.
For further information, see "Writing Common Code for .NET Data Providers", as well as "HOW TO: Use Base Classes to Reduce Code Forking with Managed Providers in Visual Basic .NET" (the C# version of the same article is available at HOW TO: Use Base Classes to Reduce Code Forking with Managed Providers in Visual C# .NET).
Q I want to issue a call (such as a WinHttp call) that can send an HTTP GET to retrieve a Web page using JScript®. Is it possible to use JScript .NET in this situation?
A JScript .NET is the JScript language compiled to target the common language runtime (CLR). It uses the .NET base class library that contains the HttpWebRequest class and other classes to do this. However, such code would not work as embedded script in current script hosts like Microsoft Internet Explorer. If you want to use regular JScript, you can use the XMLHTTP component on the client side, and the ServerXMLHTTP component on the server.
Q In Internet Explorer, if the user navigates to the previous page using the Back button, is there any way to locate where in window.history the user is currently? Is it possible to get the URL? I am trying to handle session variables when multiple windows are opened. I keep a copy of session variables for each window and attempt to maintain the mapping. But this strategy does not work if the user opens a new window using Control-N and then goes backwards in the new window to perform some task. I am trying to keep the user from going back past the page on which the new window was opened.
A First of all, you can't read history information. You can only use window.history.back and window.history.forward to navigate backward and forward. Window.history.length will tell you how many elements are in the history list. Allowing access to the URL would be a huge security issue. Consider what a hostile Web page would do with that information. The URL history contains all kinds of private data—not just what Web sites you visit, but URLs often contain information about products you've looked at, what your user name is on various Web sites, what queries you sent recently, and lots more private data.
If you read the MSDN® docs for IomHistory, the property type for IHTMLWindow2::history, you'll see only the following exposed to automation through the dispatch interface:
- back(*pvargdistance : VARIANT)
- forward()
- go(*pvargdistance : VARIANT)
- get_length(*p : short)
Most browsers will pass a referrer URL to a server in response to a request (though there are many cases where it won't, or it'll pass something intentionally wrong). On the server you can pick up that URL and perform any logic you need, or pass it back to the client as part of the content. There's no guarantee you'll get it though.
If you want to get page history from your own site, you might consider storing page history in cookies on the client. For example, every time a page loads, add its name or some kind of ID to a cookie. Just keep in mind that in the multiple-window situation you mentioned, the cookies will be the same for both windows. Modifications you make to one window will happen in the other one, too. To be safe in cases in which the user uses multiple windows, you can consider using state logic. This issue is one of biggest challenges of Web development.
Q I have a JavaScript file that has a number of useful functions that I'm trying to incorporate into a new ASP.NET site. However, I get errors wherever WScript is used in the various functions. The following line produces a "WScript is undefined" error:
var _LogFile = WScript.StdOut;My search for documentation revealed that WScript usage requires Cscript.exe to be the host. I would really like to avoid rewriting the script functions so I need to know if there's any way to incorporate it in the ASP.NET site as is? I'm using JavaScript on the client:
<script language="JavaScript" src="CommonScripts.js">
document.write('<BR/><B> Current Date = ' & _logCurDate & '<B><BR/>');
</script>
CommonScripts.js is the file that has all the functions I want to use (with _logCurDate being one of them).
A If you're using client-side script, then the question really doesn't involve ASP.NET. You would see the same results/limitations if you were to use a simple static HTML file. WScript is an object provided by the Windows Scripting Host and is not applicable inside of Internet Explorer or on the server side.
You are not likely find a way to simply retrofit the existing scripts to a different object model. You will need to find the functionality provided in whichever object model is provided by your script engine and replace those function calls.
If it's client-side JavaScript, then you need to look at the objects like document and window. If it is server-side ASP with JavaScript, look at the Request/Response objects (additionally, you can instantiate the FileSystemObject). If you are using ASP.NET, then use Request/Response/Page, and so on.
Got a question? Send questions and comments to webqa@microsoft.com.
Thanks to the following Microsoft developers for their technical expertise: Yasir Alvi, Gaurav Bansal, Mike Barrett, Kawarjit Bedi, Todd Carter, Hitesh Chaudhary, Saurabh Dasgupta, Lale Divringi, David Ebbo, Chris Gariepy, Mick Hakobyan, Koce Ivanov, Ronghua Jin, Eric Lawrence, Erik Leaseburg, Xin (Sheen) Li, Eric Lippert, David Lovell, Richie Meyer, Satvir Randhawa, Angel Saenz-Badillos, Kurt Schenk, Fyodor Soikin, Heath Stewart, and Charles Torre.