Visual Studio notes Visual Studio notes

Web configuration notes

Quick steps to create a web service

Changing table columns

… requires: The web form dataset and datagrid will be fed from the above changes and not require further configuration.

ReNaming

If a name starts with a number, code references will prefix that number with an underscore. … the default web URL
… the Client application and Namespace

If you do so, rename any references to the Namespace e.g. in the web form .aspx.cs file. … the web form
Renaming in the properties does not change code references e.g. in public class webForm1.

Web services

Path to a web service is set in the web reference folder properties.  Capturing web service data adapter changes requires deleting and re-creating the web reference.

Data-access Notes

Data-access components

A data connection stores connection & authentication information.
A data adaptor is analogous to a query in that it stores SQL statements, calls stored procedures etc.
A dataset is an in-memory data cache.  A dataset can contain multiple tables, their relationships and constraints.  If your program needs to perform a sequential, read-only pass through a query result, you can use a data reader object in place of filling a dataset.
A datagrid is the primary (flexible) control to display database data.
For a web service, the data connector, data adapter go in the web service project (for interaction with the data source); the dataSet and dataGrid (for display) goes in the web form project.

DataGrids

Controlling Edit mode

Set the DataGrid control's EditItemIndex property to the index (zero-based) of the row to edit.  For example, to put the third row into edit mode, you set the property to 2.  To return a row to display mode, you set the property to –1.

After changing edit mode, re-bind the grid to display the row data.

Determining what row to Edit

… from the event-object, passed to the handler.  The event object for these events contains an Item property, representing the DataGrid row being updated.  The Item object in turn supports various properties, including the Item.ItemIndex property, which returns the index value of the current row.

Web Services data access

Web Service DataGrid WebMethods

The [WebMethod] declaration is necessary for each web method; grouping several methods under one [WebMethod] declaration doesn’t work.

When keeping track of your objects in code, remember that what you’re exposing from the web service is a dataset (of in-memory cache).  The exposed web service methods operate on the in-memory dataset (not on the class or web service, itself).

The web service dataSet Get WebMethod

[WebMethod]
  public datasetTableName GetTableName()
  {
    datasetTableName  objectInstanceTableName = new datasetTableName();
    dataAdapterTableName.Fill(objectInstanceTableName);
    return  objectInstanceTableName;
  }

The web service dataSet Update WebMethod

[WebMethod]
Public datasetTableName UpdateTableName(datasetTableName  datasetChanges)
{
	if (datasetChanges  != null)
	{
    	dataAdapterTableName.UpdateTableName(datasetChanges);
    	return  datasetChanges;
	}
	else
	{
		return  null;
	}
}

Web Service dataSet Delete WebMethod

[WebMethod]
public datasetTableName  DeleteTableName(datasetTableName TableNameDeleteRow)
{
	// If there's a  row to delete,
	if  (TableNameDeleteRow!= null)
    {
        // pass the row-to-delete to DeleteCommand Parameters  collection
        //  sqlDeleteCommand1 was created by Delete event-creation wizard
        // @Original_TableID was created by Delete event-creation  wizard
        sqlDeleteCommand1.Parameters["@Original_TableID"].Value =  TableNameDeleteRow;
    
        // execute the data adapter DeleteCommand
        sqlDeleteCommand1.ExecuteNonQuery();
        return TableNameDeleteRow;
    }
	else
	{
		return null;
	}
}

Web Service IIS and web.config Security

In order to work over the Internet, as opposed to across a Windows LAN, "Forms", rather than "Windows", authentication is required.

The IIS directory security worked for the web service with "Integrated Security" and "Anonymous access" unchecked.  The web.config file worked for the web service with the following settings: <authentication mode="Forms" /> <authorization> <allow users="ASPNET" /> </authorization> ASPNET is the Windows account, used by ASP.Net framework e.g. for SQL Server access.

SQL Server web service security

For "Forms" authentication, skip <identity impersonate="true" /?> and add the ASPNET account to the SQL Server by Login name: -> pulldown <new> -> Name ... and pick ASPNET from the Windows accounts list.  You'll also need to add Select, Insert, Update & Delete etc. Permissions on whatever SQL Server table on which your web service acts.  This can be done via Group-level Permissions, rather than individual table permissions.  For instance, instead of adding individual table Select, Insert, Update & Delete Permissions for ASPNET, you could add db_datareader and db_datawriter Permissions for ASPNET for the whole database, if desired.

Web Form DataGrid Events

Web form dataSet UpdateCommand Event

private void dataGridTableName_UpdateCommand(object source, System.Web.UI.WebControls.DataGridCommandEventArgs e)
	{
		// set integer  to first editable column number (2)
		// increment  the For loop integer until it reaches the dataset columns count
		for (int i=2; i <=  webFormDataSetDataSourceName.TableName.Columns.Count; i++)
		{
			// Controls[0] is the TextBox  control.
			// Assign the datagrid TextBox to  a local TextBox variable.
			// Since the ID column TextBox is  "out of range of valid values",
			// use the next TextBox [i+1].  This was only necessary when Delete column
			// was added - in addition to the  Edit column. Why ?
			TextBox txtGrid = (TextBox)(e.Item.Cells[i+1].Controls[0]);

			// assign the table dataset index value to a local DataRow variable
			DataRow dgRow =  webFormDataSetDataSourceName.DataSourceName[e.Item.DataSetIndex];

			// Assign edited TextBox values to  editable dataset columns caption property
			// Use [i-1] because you can't  assign values to the ID column, #1
			// therefore, there are [i-1]  columns that can be edited
			dgRow[webFormDataSetDataSourceName.DataSourceName.Columns[i-1].Caption] =  txtGrid.Text;
		}

		// if there are  changes, update the data source
		if  (webFormDataSetDataSourceName.HasChanges())
		{
			// create a web service instance
			AppName.localhost.AppNameService webServiceInstanceName = new AppName.localhost.AppNameService();

			// assign default system credentials to the web service instance
			webServiceInstanceName.Credentials =  System.Net.CredentialCache.DefaultCredentials;

			// Create web-service (NOT web-form) dataSet instance
			AppName.localhost.DataSetDataSourceName DataSourceNameDifferences = new AppName.localhost.DataSetDataSourceName();

			// Merge/assign web form dataset changes into web service  dataset instance.
			DataSourceNameDifferences .Merge(webFormDataSetDataSourceName.GetChanges());

			// update the web service with the web service differences
			webServiceInstanceName.UpdateDataSourceName(DataSourceNameDifferences);

			// merge the web service differences back to the web form dataset
			webFormDataSetDataSourceName.Merge(DataSourceNameDifference);
		}

		// if no  changes, set datagrid editing to False and rebind
		dataGridDataSourceName.EditItemIndex =  -1;
		dataGridDataSourceName.DataBind(); 
  }

Web  form DeleteCommand Event

// web form dataSet DeleteCommand
private void dgMfgr_DeleteCommand(object  source, System.Web.UI.WebControls.DataGridCommandEventArgs e)
{
	// create a web  service instance
TableNameApp.localhost.TableNameService webServiceInstance = new TableNameApp.localhost.TableNameService (); // assign default system credentials to the web service instance webServiceInstance.Credentials = System.Net.CredentialCache.DefaultCredentials; // Create web-service (NOT web-form) dataSet instance TableNameApp.localhost.dataSetTableName webServiceDataSetTableNameDifference = new TableNameApp.localhost.webServiceDataSetTableName(); // assign row, chosen for deletion, to a local DataRow variable
DataRow rowToDelete = webFormDataSetTableName.TableName[e.Item.ItemIndex];
// call row-to-delete Delete function rowToDelete.Delete(); // merge the web form dataset differences back to the web service dataset webServiceDataSetTableNameDifference.Merge(webFormDataSetTableName.GetChanges()); // call the web service Update method webServiceInstance.UpdateMfgr(webServiceDataSetTableNameDifference); // re-bind the datagrid - to update the display dataGridTableName.DataBind(); }

Web Form Add dataGrid row Event

This function needs to work in conjunction with the Page Load function.
private void bAddRow_Click(object  sender, System.EventArgs e)
{
	// instantiate a DataRow object with a new row
	DataRow drNew = webFormDataSetTableName.TableName.NewRow(); 
// supply a value - to hold the row drNew["TableName"] = "(New)";
// insert new row at end of table, so auto incrementer can assign ID webFormDataSetTableName.TableName.Rows.InsertAt(drNew, webFormDataSetTableName.TableName.Rows.Count);
// Save dataSet in session state - so a datasource refresh won't overwrite it. Session["webFormDataSetTableName"] = webFormDataSetTableName;
// re-bind the datagrid dataGridTableName.DataBind();
}

private void Page_Load(object sender, System.EventArgs e) { // create an application-service-type web service instance TableNameApp.localhost.TableNameSvc webServiceInstance = new TableNameApp.localhost.TableNameSvc();
// assign default credentials to the web service instance wsi.Credentials = System.Net.CredentialCache.DefaultCredentials;
// populate the dataset by calling the GetMfgr function webFormDataSetTableName.Merge(webServiceInstance.GetTableName()); // if it's a postback, bind it to session state dataSet if (Page.IsPostBack) { // Cast session dataSet as the application dataSet // Assign the session dataSet to the form dataSet // to prevent overwriting a new record with the source table. webFormDataSetTableName = (TableNameApp.localhost.dsMfgr) Session["webFormDataSetTableName"]; } else { // Assign the session dataSet Session["webFormDataSetTableName"] = webFormDataSetTableName;
// bind the dataGrid dataGridTableName.DataBind();
} }

Security

The authenticate.aspx page provides the authentication web service credentials lookup.  The following code is pertinent from its web.config page.
<authentication mode="Forms">
	<forms loginUrl = "login.aspx" />
</authentication>

<authorization> <allow users="ASPNET" /> </authorization>

Authenticate.aspx page

// Wizard-generated code for connections, data adapters  etc. were omitted for brevity.
// System.Web.Security is required to provide FormsAuthentication.Redirect  …
using System.Web.Security;
namespace AuthenticateSvcDatabaseTableName
{
	public  class AuthenticateSvc :  System.Web.Services.WebService
{ public AuthenticateSvc() { // sqlSelectCommand1 this.sqlSelectCommand1.CommandText = "SELECT COUNT(*) AS matchCount FROM Credentials WHERE (CAST(RTRIM(UserName) AS Var" + Binary) = CAST(RTRIM(@UserName) AS VarBinary)) AND (CAST(RTRIM(Password) AS VarB" + Binary) = CAST(RTRIM(@Password) AS VarBinary))"; this.sqlSelectCommand1.Connection = this.conn3P; this.sqlSelectCommand1.Parameters.Add(new System.Data.SqlClient.SqlParameter("@UserName", System.Data.SqlDbType.VarChar)); this.sqlSelectCommand1.Parameters.Add(new System.Data.SqlClient.SqlParameter("@Password", System.Data.SqlDbType.VarChar)); }

[WebMethod] public bool AuthenticateUser(string UserName, string Password) { // Pass supplied user & password to lookup SQLcommand object parameters collection. sqlSelectCommand1.Parameters["@UserName"].Value = UserName; sqlSelectCommand1.Parameters["@Password"].Value = Password;

// open the da connection conn3P.Open();

// run the match-selection command int matches = (int) sqlSelectCommand1.ExecuteScalar();

// close the connection after use conn3P.Close();

// match Selection returns match Count. // >1 found a match i.e. authenticated.
return (matches > 0); }

Login.aspx page

The Authenticate.aspx page is called by a Login.aspx page, which instigates the authentication web service via a button click.  The button-click event contains a web service instance.  The wsi.AuthenticateUser method returns a Boolean true/false indicator of authentication.  If authenticated, the FormsAuthentication.RedirectFromLoginPage method redirects the user back from Login.aspx to the desired page.
private  void btnLogin_Click(object  sender, System.EventArgs e)
{
	//  assign user TextBox inputs to local variables
	string  user = txtUserName.Text;
	string  pw = txtPassword.Text;

	//  Initialize a boolean authentication variable as false.
bool bAuthenticated = false; // create web service instance
MfgrApp.authenticateSvc.AuthenticateSvc wsi = new MfgrApp.authenticateSvc.AuthenticateSvc();

// assign default credentials to the web service instance wsi.Credentials = System.Net.CredentialCache.DefaultCredentials;

// Assign boolean result of passing user/password to // web service instance AuthenticateUser method bAuthenticated = wsi.AuthenticateUser(user, pw);

// If true (i.e. authenticated),
if (bAuthenticated)

// Call the FormsAuthentication Redirect method to return to requesting page. // User names the cookie.  false gives the cookie the default 30 minutes. FormsAuthentication.RedirectFromLoginPage(user, false); else // If bAuthenticated is false, deliver the "get lost" message.
lblStatus.Text = "Status:  Your UserName or Password was not found."; }

Update errors

ArgumentOutOfRangeException

This may be due to the fact that you can’t update the keyID column.  In the data adapter properties, remove keyID column from the Update (or other event) Parameters | Collection.

Deployment

File sharing is now recommended over Front Page Server Extensions (FPSE); Visual Source Safe can work with file sharing better than FPSE.

Copy Project …

Getting “Copy a project …” to work required disabling Norton Internet Security on the source (not target) PC; otherwise, an error dialog box complained that "Visual Studio could not identify the version of ASP.NET on the Web server."

Backup

Web projects

Backing up Visual Studio project work, particularly involving web projects, requires more than backing up:  \My Documents\Visual Studio Projects\.  Web project files are kept IN the website directory; therefore, it’s necessary to back up the website(s), too.  To get all websites, backup drive:\Inetpub\wwwroot\ … or better, yet, drive:\Inetpub\.

Errors

"Visual Studio could not identify the version of ASP.NET on the Web server."
Disabling the software firewall on the Visual Studio (source) PC, doing the copying, got rid of this error; disabling the firewall on the recipient (target) PC did not prove necessary.

“Visual Studio .Net has detected that the web server is not running ASP.Net version 1.1.  You will be unable to run ASP.Net web applications  or services.”
ASP.Net1.1
Apparently this error is thrown when the version of ASP.Net is not "registered", even though it was installed.  The following ends the error:
C:\WINDOWS\Microsoft.NET\Framework\v1.0.4322\aspnet_regiis.exe -i

Note that the 4322 version may/should be replaced with the latest framework version, you have.  The –i switch installs the given version.

Back Home