Web configuration notes
Quick steps to create a web service
- VS.Net | New Project
- Select development language (e.g. C# or VB)
- Choose the “ASP.Net web Service” project template from the right-pane.
- Uncomment and/or edit code, build the project and Run (F5) the project
- Type the new web service URL location
Changing table columns
… requires:- re-configuring the web service data adapter
- deleting and re-generating the web service data set
- deleting and re-creating the web form web reference
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
ArgumentOutOfRangeExceptionThis 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.”

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