Один из тестеров в моей компании обнаружил ошибку в моем решении ASP.Net MVC 3, которая, как мне кажется, встречается довольно часто.
Один пост на сервере, который он может обработать. Но если вы отправляете много сообщений, например, атака типа «отказ в обслуживании» (DoS атака) , возникает исключение:
Server Error in '/' Application.
Initializing[UseSoft.ProdMaster.Domain.Entities.CustomerOrderHeader#567]-failed to lazily initialize a collection of role: UseSoft.ProdMaster.Domain.Entities.CustomerOrderHeader.CustomerOrderLines, no session or session was closed
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.
Exception Details: NHibernate.LazyInitializationException: Initializing[UseSoft.ProdMaster.Domain.Entities.CustomerOrderHeader#567]-failed to lazily initialize a collection of role: UseSoft.ProdMaster.Domain.Entities.CustomerOrderHeader.CustomerOrderLines, no session or session was closed
Source Error:
Line 880:
Line 881:
Line 882: return
Line 883: Json(
Line 884: new
Source File: C:\Projects\DavidPM\Hosts\ProdMaster.Hosts.Web\Areas\Sales\Controllers\CustomerOrderController.cs Line: 882
Stack Trace:
[LazyInitializationException: Initializing[UseSoft.ProdMaster.Domain.Entities.CustomerOrderHeader#567]-failed to lazily initialize a collection of role: UseSoft.ProdMaster.Domain.Entities.CustomerOrderHeader.CustomerOrderLines, no session or session was closed]
NHibernate.Collection.AbstractPersistentCollection.ThrowLazyInitializationException(String message) in d:\CSharp\NH\NH\nhibernate\src\NHibernate\Collection\AbstractPersistentCollection.cs:484
NHibernate.Collection.AbstractPersistentCollection.ThrowLazyInitializationExceptionIfNotConnected() in d:\CSharp\NH\NH\nhibernate\src\NHibernate\Collection\AbstractPersistentCollection.cs:474
NHibernate.Collection.AbstractPersistentCollection.Initialize(Boolean writing) in d:\CSharp\NH\NH\nhibernate\src\NHibernate\Collection\AbstractPersistentCollection.cs:465
NHibernate.Collection.AbstractPersistentCollection.Read() in d:\CSharp\NH\NH\nhibernate\src\NHibernate\Collection\AbstractPersistentCollection.cs:264
NHibernate.Collection.Generic.PersistentGenericBag`1.System.Collections.Generic.IEnumerable<T>.GetEnumerator() in d:\CSharp\NH\NH\nhibernate\src\NHibernate\Collection\Generic\PersistentGenericBag.cs:142
System.Linq.WhereSelectEnumerableIterator`2.MoveNext() +63
System.Linq.Buffer`1..ctor(IEnumerable`1 source) +217
System.Linq.Enumerable.ToArray(IEnumerable`1 source) +78
UseSoft.ProdMaster.Hosts.Web.Areas.Sales.Controllers.CustomerOrderController.SaveOrUpdateOrderLines(CustomerOrderModel customerOrderModel) in C:\Projects\DavidPM\Hosts\ProdMaster.Hosts.Web\Areas\Sales\Controllers\CustomerOrderController.cs:882
lambda_method(Closure , ControllerBase , Object[] ) +162
System.Web.Mvc.ActionMethodDispatcher.Execute(ControllerBase controller, Object[] parameters) +17
System.Web.Mvc.ReflectedActionDescriptor.Execute(ControllerContext controllerContext, IDictionary`2 parameters) +208
System.Web.Mvc.ControllerActionInvoker.InvokeActionMethod(ControllerContext controllerContext, ActionDescriptor actionDescriptor, IDictionary`2 parameters) +27
System.Web.Mvc.<>c__DisplayClass15.<InvokeActionMethodWithFilters>b__12() +55
System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodFilter(IActionFilter filter, ActionExecutingContext preContext, Func`1 continuation) +263
System.Web.Mvc.<>c__DisplayClass17.<InvokeActionMethodWithFilters>b__14() +19
System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodWithFilters(ControllerContext controllerContext, IList`1 filters, ActionDescriptor actionDescriptor, IDictionary`2 parameters) +191
System.Web.Mvc.ControllerActionInvoker.InvokeAction(ControllerContext controllerContext, String actionName) +343
System.Web.Mvc.Controller.ExecuteCore() +116
System.Web.Mvc.ControllerBase.Execute(RequestContext requestContext) +97
System.Web.Mvc.ControllerBase.System.Web.Mvc.IController.Execute(RequestContext requestContext) +10
System.Web.Mvc.<>c__DisplayClassb.<BeginProcessRequest>b__5() +37
System.Web.Mvc.Async.<>c__DisplayClass1.<MakeVoidDelegate>b__0() +21
System.Web.Mvc.Async.<>c__DisplayClass8`1.<BeginSynchronous>b__7(IAsyncResult _) +12
System.Web.Mvc.Async.WrappedAsyncResult`1.End() +62
System.Web.Mvc.<>c__DisplayClasse.<EndProcessRequest>b__d() +50
System.Web.Mvc.SecurityUtil.<GetCallInAppTrustThunk>b__0(Action f) +7
System.Web.Mvc.SecurityUtil.ProcessInApplicationTrust(Action action) +22
System.Web.Mvc.MvcHandler.EndProcessRequest(IAsyncResult asyncResult) +60
System.Web.Mvc.MvcHandler.System.Web.IHttpAsyncHandler.EndProcessRequest(IAsyncResult result) +9
System.Web.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +8862381
System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +184
Описано ниже:
Нажмите на кнопку много раз. Или нажмите один раз и нажмите Enter, он отправит много запросов на сервер «Пост».
Модель в основном:
public class CustomerOrderModel
{
public CustomerOrderModel()
{
this.CustomerOrderLines = new List<CustomerOrderLineModel>();
this.CustomerOrderHeader = new CustomerOrderHeaderModel();
}
public CustomerOrderHeaderModel CustomerOrderHeader
{ get; set; }
public List<CustomerOrderLineModel> CustomerOrderLines
{ get; set; }
}
Контроллер:
[HttpPost]
public JsonResult SaveOrUpdateOrderLines( CustomerOrderModel customerOrderModel)
{
if (customerOrderModel.CustomerOrderHeader.OrderNumber == 0)
{
customerOrderModel.CustomerOrderHeader.OrderNumber = this.CustomerOrderService.CreateOrUpdate(customerOrderHeader, false);
}
возврат
Json (
новый
{
OrderNumber = customerOrderModel.CustomerOrderHeader.OrderNumber,
CustomerOrderLines = новый
{
CustomerOrderLine = (
от ordeline в custOrderHeader.CustomerOrderLines
выберите новый
{
Id = ordeline.Id,
LineNumber = ordeline.LineNumber,
LineStatus = ordeline.LineStatus
}
).ToArray()
}
},
JsonRequestBehavior.AllowGet
);
}
Служба CustomerOrder:
public class CustomerOrderService : ServiceBase, ICustomerOrderService
{
public long CreateOrUpdate(CustomerOrderHeader customerOrderHeader, bool updateCustomerOrderHeader)
{
using (var session = this.SessionManager.OpenSession())
{
var transaction = session.BeginTransaction();
try
{
//TODO: CHECKS IF PARTNER EXISTS
bool existsPartner = false;
long number = 0;
if (this.PartnerService.FindByName(customerOrderHeader.Partner.Name) != null)
{
existsPartner = true;
}
//CREATE PARTNER AND PARTNER ADDRESSES
if (!existsPartner)
{
this.PartnerService.Create(customerOrderHeader.Partner as Partner);
}
if (!updateCustomerOrderHeader)
{
number = this.CustomerOrderHeaderService.Create(customerOrderHeader, true);
}
else
{
this.CustomerOrderHeaderService.Create(customerOrderHeader, false);
}
transaction.Commit();
return number;
}
catch (Exception ex)
{
transaction.Rollback();
throw ex;
}
finally
{
session.Close();
}
}
}
/// <summary>
/// Initializes a new instance of the <see cref="CustomerOrderService"/> class.
/// </summary>
/// <param name="sessionManager">
/// The session manager.
/// </param>
public CustomerOrderService(ISessionManager sessionManager)
{
this.SessionManager = sessionManager;
}
}
Служба CustomerOrderHeaderService:
public long Create(CustomerOrderHeader customerOrderHeader, bool firstTime)
{
using (var session = this.SessionManager.OpenSession())
{
// var transaction = session.BeginTransaction();
// try
// {
if (firstTime)
{
foreach (var customerOrderLine in customerOrderHeader.CustomerOrderLines)
{
customerOrderLine.CustomerOrderHeader = customerOrderHeader;
}
customerOrderHeader.OrderNumber = this.NextOrderNumber();
session.Save(customerOrderHeader);
}
else
{
CustomerOrderHeader customerOrderHeaderToBeChanged =
this.FindByOrderNumber(customerOrderHeader.OrderNumber);
customerOrderHeaderToBeChanged.CopyDomainProperties(
customerOrderHeader, new[]
{
"Id",
"Partner",
"DataOwner",
"dataOwner",
"SysCreatedOn",
"SysCreatedBy",
"CustomerOrderLines"
});
customerOrderHeaderToBeChanged = UpdateLines(customerOrderHeader, customerOrderHeaderToBeChanged);
List<ICustomerOrderLine> linestoBeInserted = GetTheLineNumbersToBeInserted(customerOrderHeader);
foreach (var customerOrderLine in linestoBeInserted)
{
customerOrderHeaderToBeChanged.CustomerOrderLines.Add(customerOrderLine);
customerOrderLine.CustomerOrderHeader = customerOrderHeaderToBeChanged;
}
session.Update(customerOrderHeaderToBeChanged);
}
// transaction.Commit();
}
// catch (Exception ex)
// {
// transaction.Rollback();
// throw ex;
// }
// finally
// {
// session.Close();
// }
//}
//throw new System.ArgumentException();
return customerOrderHeader.OrderNumber;
}
public class CustomerOrderHeaderService : ServiceBase, ICustomerOrderHeaderService
{
#region Constructors and Destructors
/// <summary>
/// Initializes a new instance of the <see cref="CustomerOrderHeaderService"/> class.
/// </summary>
/// <param name="sessionManager">
/// The session manager.
/// </param>
public CustomerOrderHeaderService(ISessionManager sessionManager)
{
this.SessionManager = sessionManager;
}
#endregion
public long Create(CustomerOrderHeader customerOrderHeader, bool firstTime)
{
using (var session = this.SessionManager.OpenSession())
{
// var transaction = session.BeginTransaction();
// try
// {
if (firstTime)
{
foreach (var customerOrderLine in customerOrderHeader.CustomerOrderLines)
{
customerOrderLine.CustomerOrderHeader = customerOrderHeader;
}
customerOrderHeader.OrderNumber = this.NextOrderNumber();
session.Save(customerOrderHeader);
}
else
{
CustomerOrderHeader customerOrderHeaderToBeChanged =
this.FindByOrderNumber(customerOrderHeader.OrderNumber);
customerOrderHeaderToBeChanged.CopyDomainProperties(
customerOrderHeader, new[]
{
"Id",
"Partner",
"DataOwner",
"dataOwner",
"SysCreatedOn",
"SysCreatedBy",
"CustomerOrderLines"
});
customerOrderHeaderToBeChanged = UpdateLines(customerOrderHeader, customerOrderHeaderToBeChanged);
List<ICustomerOrderLine> linestoBeInserted = GetTheLineNumbersToBeInserted(customerOrderHeader);
foreach (var customerOrderLine in linestoBeInserted)
{
customerOrderHeaderToBeChanged.CustomerOrderLines.Add(customerOrderLine);
customerOrderLine.CustomerOrderHeader = customerOrderHeaderToBeChanged;
}
session.Update(customerOrderHeaderToBeChanged);
}
// transaction.Commit();
}
// catch (Exception ex)
// {
// transaction.Rollback();
// throw ex;
// }
// finally
// {
// session.Close();
// }
//}
//throw new System.ArgumentException();
return customerOrderHeader.OrderNumber;
}
}