问题
I have an ASP.NET web forms site using Master Pages. It is using Unity as my IoC container. I have created an HTTP Module to build up the container using a couple of tutorials i found online. I need the dependency injection to work for User Controls and the only way i was able to get this to work was to hook into the Pages PreInit event as can be seen from the code below.
public class UnityHttpModule : IHttpModule
{
public void Init(HttpApplication context)
{
context.PreRequestHandlerExecute += OnPreRequestHandlerExecute;
}
public void Dispose() { }
private void OnPreRequestHandlerExecute(object sender, EventArgs e)
{
IHttpHandler currentHandler = HttpContext.Current.Handler;
HttpContext.Current.Application.GetContainer().BuildUp(
currentHandler.GetType(), currentHandler);
// User Controls are ready to be built up after page initialization is complete
var currentPage = HttpContext.Current.Handler as Page;
if (currentPage != null)
{
currentPage.PreInit += Page_PreInit;
}
}
// Build up each control in the page's control tree
private void Page_PreInit(object sender, EventArgs e)
{
var currentPage = (Page)sender;
BuildUp(currentPage);
BuildUpMaster(currentPage.Master);
BuildUpControls(currentPage.Controls);
}
private void BuildUp(object o)
{
HttpContext.Current.Application.GetContainer().BuildUp(o.GetType(), o);
}
private void BuildUpControls(ControlCollection controls)
{
foreach (Control c in controls)
{
if (c is UserControl)
BuildUp(c);
BuildUpControls(c.Controls);
}
}
private void BuildUpMaster(MasterPage page)
{
if (page != null)
{
BuildUp(page);
BuildUpMaster(page.Master);
}
}
}
My pages and controls all inherit off base implementations which handle the dependency injection e.g.
public class MyBaseUserControl : UserControl
{
[Dependency]
public IMyServiceProvider MyService { get; set; }
}
public class MyPage : Page
{
[Dependency]
public IMyServiceProvider MyService { get; set; }
}
My Dependency Injection is working as planned, however when I use GridViews on my pages the OnRowEditing etc commands dont fire for the GridView. Its as if the events arent hooked up. I have set the events in the HTML as follows.
<asp:GridView ID="gvComplaintCategory" runat="server" AutoGenerateColumns="False" DataKeyNames="ComplaintCategoryID" BackColor="#FFFFFF" GridLines="None"
CellPadding="2" CellSpacing="2" AllowPaging="True" PageSize="8" ShowFooter="true"
OnRowCommand="gvComplaintCategory_OnRowCommand"
OnRowEditing="gvComplaintCategory_OnRowEditing"
OnRowCancelingEdit="gvComplaintCategory_OnRowCancelingEdit">
<asp:TemplateField>
<HeaderTemplate>Complaint Category Name</HeaderTemplate>
<EditItemTemplate>
<asp:TextBox ID="txtComplaintCategoryEdit" runat="server" CssClass="textbox" Text='<%# DataBinder.Eval(Container.DataItem, "ComplaintCategoryName") %>'></asp:TextBox>
<asp:RequiredFieldValidator ID="rfvComplaintCategoryEdit" runat="server" ControlToValidate="txtComplaintCategory" Text="*" CssClass="RequiredFieldValidator" ValidationGroup="dgComplaintCategory"></asp:RequiredFieldValidator>
</EditItemTemplate>
<ItemTemplate>
<asp:Label ID="lblComplaintCategory" runat="server" CssClass="label" Text='<%# DataBinder.Eval(Container.DataItem, "ComplaintCategoryName") %>'></asp:Label>
</ItemTemplate>
<FooterTemplate>
<asp:TextBox ID="txtComplaintCategoryNew" runat="server" CssClass="textbox"></asp:TextBox>
<asp:RequiredFieldValidator ID="rfvComplaintCategoryNew" runat="server" ControlToValidate="txtComplaintCategoryNew" Text="*" CssClass="RequiredFieldValidator" ValidationGroup="dgComplaintCategory"></asp:RequiredFieldValidator>
</FooterTemplate>
</asp:TemplateField>
<asp:TemplateField>
<EditItemTemplate>
<asp:Button ID="btnComplaintCategoryUpdate" runat="server" CssClass="button" CommandName="Update" Text="Update" CausesValidation="true" ValidationGroup="dgComplaintCategory"/>
<asp:Button ID="btnComplaintCategoryDelete" runat="server" CssClass="button" CommandName="Delete" Text="Delete" CausesValidation="false" ValidationGroup="dgComplaintCategory"/>
<asp:Button ID="btnComplaintCategoryCancel" runat="server" CssClass="button" CommandName="Cancel" Text="Cancel" CausesValidation="false" ValidationGroup="dgComplaintCategory"/>
</EditItemTemplate>
<ItemTemplate>
<asp:Button ID="btnComplaintCategoryEdit" runat="server" CssClass="button" CommandName="Edit" Text="Edit" CausesValidation="false" ValidationGroup="dgComplaintCategory"/>
</ItemTemplate>
<FooterTemplate>
<asp:Button ID="btnComplaintCategoryAdd" runat="server" CssClass="button" CommandName="Add" Text="Add" CausesValidation="true" ValidationGroup="dgComplaintCategory"/>
</FooterTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
I also have autoeventwireup set to true on the pages and master page. Can anyone shed any light on why the events are not firing? Is my Unity http module causing this to happen by dropping the event wiring? I can get this to work no problem in a basic example with no IoC involved.
Any help would be greatly appreciated.
Thanks
Matt
回答1:
The reason is that you are modifying the controls before they load their ViewState.
Moving build-up on PreLoad should work, because ViewState is loaded before the PreLoad event
private void OnPreRequestHandlerExecute(object sender, EventArgs e)
{
IHttpHandler currentHandler = HttpContext.Current.Handler;
HttpContext.Current.Application.GetContainer().BuildUp(
currentHandler.GetType(), currentHandler);
// User Controls are ready to be built up after page initialization is complete
var currentPage = HttpContext.Current.Handler as Page;
if (currentPage != null)
{
currentPage.PreInit += Page_PreInit;
currentPage.PreLoad += Page_PreLoad;
}
}
// Build up each control in the page's control tree
private void Page_PreInit(object sender, EventArgs e)
{
var currentPage = (Page)sender;
BuildUp(currentPage);
BuildUpMaster(currentPage.Master);
}
private void Page_PreLoad(object sender, EventArgs e)
{
var currentPage = (Page)sender;
BuildUpControls(currentPage.Controls);
}
来源:https://stackoverflow.com/questions/4852396/asp-net-4-0-gridview-onrowediting-events-not-firing-when-using-unity-2-0-http-mo