I just did several government projects, to talk about a few of my experience:
Governments usually hierarchical management, divided into: state, county, city, etc., divided into sections for each level of government units responsible for different tasks, can be called "role", the staff belonging to a administrative division, with one or more roles.
General government departments, higher-level units can manage subordinate data, so, using incremental encoder is relatively simple, such as 330102, 33 (state), 01 (county), 02 (City), with: xxx like '3301% 'access to 3301 County (including sub-districts) of the data; Each role has a number of menu items, a very simple permissions system, no elaboration.
In addition, about custom fields, you need to add a metadata dictionary, which store each report fields, each field has a specified property belongs to which administrative divisions, when the user logs in, according to the user's administrative divisions retrieve the corresponding Fields list. Due to the different sections of the view different reports, so it does not need additional fields.
These are my conditions encountered, may not meet your case, for reference only.
Additions:
I used Asp.net 2.0 technology, database using Oracle (customer requirements).Use the WebForm to generate the user interface, do not use any other frameworks. Because other frameworks with learning costs, and demand change mostly need Coding. I want to achieve when there are changes in demand, the customer can adjust, do not rely on any other tools and environments.
Asp.net, I use the most is its WebUserControl (ascx). I put the user interface definitions stored in the database, when the user opens the document (report),generated user controls, and then combined into the WebForm.
//public class Common_CustomBill:Page
protected override void OnInit(EventArgs e)
{
base.OnInit(e);
//User Interface Definition retrieved from the database
LoadBillItems();
foreach(DataRow ARow in BillItems.Rows)
{
HtmlTableCell ACell = new HtmlTableCell();
HtmlTableRow ATableRow = new HtmlTableRow();
ATableRow.Cells.Add(ACell);
//Depending on the type load control
NovaNet.WebBase.BillItem AItem = LoadControl("BillItem/" + ARow["type"].ToString() + ".ascx") as NovaNet.WebBase.BillItem;
AItem.OrderId = ARow["OrderId"].ToString();
AItem.ID = string.Format("C{0:X}{1}", Session.SessionID.GetHashCode(), ARow["OrderId"]);
if(P.OftenFunction.SafeToString(ARow["Border"]) == "none")
{
ACell.Controls.Add(AItem);
}
else
{
HtmlGenericControl FIELDSET = new HtmlGenericControl("FIELDSET");
HtmlGenericControl Legend = new HtmlGenericControl("legend");
FIELDSET.Controls.Add(Legend);
Legend.InnerHtml = ARow["label"].ToString();
FIELDSET.Controls.Add(AItem);
ACell.Controls.Add(FIELDSET);
}
tabMain.Rows.Add(ATableRow);
AItem.BillData = Data;
//initialize the control
AItem.InitiData(ARow["content"] as byte[],ModuleName);
}
}
User control is initialized, the different types of user controls behave differently. For example, the multi-selection control is initialized CheckBoxList Items property. Special, custom type controls, initialization is generated and loaded into a separate ascx file.
public partial class Common_BillItem_CustomControl:NovaNet.WebBase.BillItem
{
public override void OnInitiData()
{
base.OnInitiData();
//FData is incoming "initialization data"
string Value = FData["code"].ToString();
//Disk file generated
string AFileName = "~/Temp/" + ModuleName +"_"+ Value.GetHashCode().ToString("X") + ".ascx";
if(!Directory.Exists(Path.GetDirectoryName(Server.MapPath(AFileName))))
Directory.CreateDirectory(Path.GetDirectoryName(Server.MapPath(AFileName)));
if(!File.Exists(Server.MapPath(AFileName)))
{
using (StreamWriter AWriter = new StreamWriter(Server.MapPath(AFileName),false, System.Text.Encoding.UTF8))
{
AWriter.Write(Value);
AWriter.Close();
}
}
//Loaded into the interface
Controls.Add(LoadControl(AFileName));
}
}
IIS dynamic compilation great. Load "ascx file" Generate "dll files", follow the direct loading "dll file".