Now we want to edit user data...
In a previous post I explained how you can the user display page (UserDisp.aspx) in WSS. Well like typical users they came back and said “Man this is cool, but it would be even better if we could now edit this information here”, instead of where it is suppose to be edited which is a whole seperate application. But being the little steam engine that can I said no sweat guys.
It was actually very easy, just a few gotchas I need to tell you about, the process is very similar to what I explained in the other post.
What I forgot to mention in the previous post was that I ended up doing all the work to get the display info in the OnLoad method. Here is the code from UserDisp.cs:
using System;
using System.Web.UI.WebControls;
using PSH.DataAccess.Model;
using Microsoft.SharePoint;
using Microsoft.SharePoint.WebControls;
namespace PSH.SharePoint.ApplicationPages
{ ///
/// Summary description for UserDisp.
///
public class UserDisp : Microsoft.SharePoint.ApplicationPages.UserDisp
{ protected Label lblJobTitle;
protected Label lblPhone;
protected Label lblFax;
protected Label lblMobile;
protected int UserID
{ get
{ if (Request.QueryString["ID"] == null)
{ return -1;
}
return int.Parse(Request.QueryString["ID"]);
}
}
protected override void OnLoad(EventArgs e)
{ base.OnLoad(e);
try
{ SPWeb site = SPControl.GetContextWeb(Context);
site.AllowUnsafeUpdates = true;
SPUser spUser = site.AllUsers.GetByID(this.UserID);
UserFactory userFactory = new UserFactory(DataAccess.Common.Context.ObjectContext());
//Could have use FindUnique, but if NEO finds no entry it throws an Exception and I didn't want that to happen.
UserList userList = userFactory.Find("NetworkName = {0}", spUser.LoginName.ToLower() ); if (userList.Count == 1)
{ User user = userList[0];
lblJobTitle.Text = user.JobTitle;
lblPhone.Text = user.Phone;
lblFax.Text = user.Fax;
lblMobile.Text = user.Mobile;
}
}
catch ()
{}
}
}
}
I use NEO for my DAL and you should just replace that with your code, sorry, but I don't have the time to go and write something generic right now. At least it give you an idea of what I did.
Ok so that was very easy, now to edit the data. So I opened UserEdit.aspx. Once again you need to change the Inherits section to look at your Assembly:
<%@ Page Language="C#" Inherits="Formway.SharePoint.ApplicationPages.UserEdit" ValidateRequest="False" %>
Then I searched for “Display Name” and found txtName is the textbox control for the users name. I copied the label and textbox and created a few for my data:
<tr>
<td class= "ms-vh"><label for="txtTitle"> Title:< SPAN>label>< SPAN>td>
<td class= "ms-propertysheet"><asp:TextBox Tabindex=5 id=txtTitle MaxLength=255 runat=server title="Title" CssClass="ms-long" />< SPAN>td>
< SPAN>tr>
<tr>
<td class= "ms-vh"><label for="txtPhone"> Phone:< SPAN>label>< SPAN>td>
<td class= "ms-propertysheet"><asp:TextBox Tabindex=5 id=txtPhone MaxLength=255 runat=server title="Phone" CssClass="ms-long" />< SPAN>td>
< SPAN>tr>
<tr>
<td class= "ms-vh"><label for="txtFax"> Fax:< SPAN>label>< SPAN>td>
<td class= "ms-propertysheet"><asp:TextBox Tabindex=5 id=txtFax MaxLength=255 runat=server title="Fax" CssClass="ms-long" />< SPAN>td>
< SPAN>tr>
<tr>
<td class= "ms-vh"><label for="txtMobile"> Mobile:< SPAN>label>< SPAN>td>
<td class= "ms-propertysheet"><asp:TextBox Tabindex=5 id=txtMobile MaxLength=255 runat=server title="Mobile" CssClass="ms-long" />< SPAN>td>
< SPAN>tr>
As you can see I only used textboxes, as this was all I needed at the moment, but you can do this with dropdownlist, checkboxes etc, whatever you need.
You can then also edit the DoValidateAndSubmit() javascript function if you want to do some client side validation of the data. I left it as it is as my data for now was not required and didn't need any special attention. So now that we have finished the aspx page which I hope you have backed up before you started editing... :D Let's focus now on our implementation of UserEdit.cs. Here is the code:
using System;
using System.Web.UI.WebControls;
using Formway.DataAccess.Model;
using Microsoft.SharePoint;
using Microsoft.SharePoint.ApplicationPages;
using Microsoft.SharePoint.WebControls;
namespace Formway.SharePoint.ApplicationPages
{ ///
/// Summary description for UserEdit.
///
public class UserEdit : Microsoft.SharePoint.ApplicationPages.UserEdit
{ protected TextBox txtTitle;
protected TextBox txtPhone;
protected TextBox txtFax;
protected TextBox txtMobile;
protected int UserID
{ get
{ if (Request.QueryString["ID"] == null)
{ return -1;
}
return int.Parse(Request.QueryString["ID"]);
}
}
protected override void OnLoad(EventArgs e)
{ CUtil.EnsureAuthentication();
SPWeb site = SPControl.GetContextWeb(Context);
SPUser spUser = site.AllUsers.GetByID(this.UserID); //site.AllUsers[user.NetworkName];
UserFactory userFactory = new UserFactory(DataAccess.Common.Context.ObjectContext());
UserList userList = userFactory.Find("NetworkName = {0}", spUser.LoginName.ToLower()); if (userList.Count == 1)
{ User user = userList[0];
if (!this.IsPostBack)
{ this.InitPage();
txtTitle.Text = user.JobTitle;
txtPhone.Text = user.Phone;
txtFax.Text = user.Fax;
txtMobile.Text = user.Mobile;
}
else
{ spUser.Name = txtName.Text;
spUser.Email = txtEmail.Text;
spUser.Notes = txtNotes.Text;
spUser.Update();
user.Email = txtEmail.Text;
user.JobTitle = txtTitle.Text;
user.Phone = txtPhone.Text;
user.Fax = txtFax.Text;
user.Mobile = txtMobile.Text;
user.Save();
this.UpdateUserInfo();
}
}
}
}
}
Now I need to point out a few things:
- As you can see I do not call base.OnLoad(e); in the OnLoad method. It works fine on the display of the data, but stuffs you up on the postback as the UpdateUserInfo() method will redirect you to another page and it gets called in base.OnLoad.
- So I call UpdateUserInfo() right after I have updated my details so that the display name, email and notes can be saved to the SPUser object and that the normal redirects can take place.
- I also call the InitPage() method to ensure that all the normal data is updated during the first display of the page.
Just remember that although this is great, if Microsoft releases a new version of WSS it will most likely override these changes, so keeping track of it somewhere (Source Control?) is essential, also documenting it is important for the poor idiot that comes after you and loses functionality when he upgrades the system. :D
I've blogged about it so who ever has to take over from me had better learn to read my blog! ;-)
[Just another important point, the profile editor on SPS is rather impossible to change, you can see just by looking at the code and different implementations in the code that there was no standard in how pages and views should work in SPS 2003 / WSS. We tried to change the SPS profile view with inheritance on another project (Armand will remember that one) but AFAIK we ended up writing our own implementation, it was a lot easier than trying to change the profile editor that came with SPS, even though we came close. It was a very bad hack though and very unstable (The inherited version, not our own implementation! :D). Hope they allow more flexibility in the next version of SPS.]