I have a problem with the system for ordering products. Scenario: Two separate browsers Two separate accounts (after logging in a separate session id) when clicked, grouped, and enabled in the connect string MultipleActiveResultSets = true.
Users click at the same time (each has different filters set, grouping), but when the second user clicks on, the user gets the result of the first user query (different parameters)
Update
[C#]
PartialViewResult AdvancedCustomBindingCore(GridViewModel viewModel)
{
UserDBModel usr = (UserDBModel)Session[SessionEl.SESSION_USER];
long _Session = System.Convert.ToInt64(usr.UserSessionID);
GridViewCustomBindingHandlers.SetModel(iMagoDataProvider.Get_f_MgKar(_Session));///////////////////-------------------ustawiamy do modelu zrodlo danych .....
if (Session["fulltextsearch"] == null)
{
GridViewCustomBindingHandlers.SetModel(iMagoDataProvider.Get_f_MgKar(_Session));
Session["fulltextsearch"] = null;
}
else
{
GridViewCustomBindingHandlers.SetModel(iMagoDataProvider.Get_f_MgKarFullTextSearch(_Session));
}
viewModel.ProcessCustomBinding(
GridViewCustomBindingHandlers.GetDataRowCountAdvanced,
GridViewCustomBindingHandlers.GetDataAdvanced,
GridViewCustomBindingHandlers.GetSummaryValuesAdvanced,
GridViewCustomBindingHandlers.GetGroupingInfoAdvanced,
GridViewCustomBindingHandlers.GetUniqueHeaderFilterValuesAdvanced
);
return PartialView("GridViewMgKarPartial", viewModel);
}
static GridViewModel CreateGridViewModelWithSummary()
{
var viewModel = new GridViewModel();///////////////////-------------------ustawiamy kolumny ze zrodla danych.....
viewModel.KeyFieldName = "SymKar;LogoP;JM;SymWL";
viewModel.Columns.Add("SymKar");
viewModel.Columns.Add("SymKarObcy");
viewModel.Columns.Add("OpiKar");
viewModel.Columns.Add("L_OpiKar_EN");
viewModel.Columns.Add("JM");
//////////////Jezeli ma byc niewidoczna to w cshtml tez sie musi zgadzac....czyli nie dodajemy
viewModel.Columns.Add("CenaNetto");
//////////////Jezeli ma byc niewidoczna to w cshtml tez sie musi zgadzac....czyli nie dodajemy
viewModel.Columns.Add("IloscPAL");
viewModel.Columns.Add("StanDys");
viewModel.Columns.Add("GruKar");
viewModel.Columns.Add("Waga");
viewModel.Columns.Add("LogoP");
viewModel.Columns.Add("RodzajHandlowy");
viewModel.Pager.PageSize = 20;
//viewModel.TotalSummary.Add(new GridViewSummaryItemState() { FieldName = "Size", SummaryType = SummaryItemType.Sum });
//viewModel.TotalSummary.Add(new GridViewSummaryItemState() { FieldName = "Subject", SummaryType = SummaryItemType.Count });
//viewModel.GroupSummary.Add(new GridViewSummaryItemState() { FieldName = string.Empty, SummaryType = SummaryItemType.Count });
return viewModel;
}
#endregion CustomBindingRoute_Settings
#region CustomBindingRoute_General
public ActionResult GridViewMgKarPartial(string selectedValues)//------------------------------------------------Ustawiamy nazwe dla View ktory powstal...........
{
int menu_pozycje_ID = System.Convert.ToInt32(Session[SessionEl.SESSION_MENU_ACT]);
UserDBModel usr = (UserDBModel)Session[SessionEl.SESSION_USER];
long _Session = System.Convert.ToInt64(usr.UserSessionID);
try
{
SortedList<string, model_Uprawnienia> rights = db.getPrawa(_Session, menu_pozycje_ID); ViewBag.Rights = rights;
}
catch (Exception e)
{
return ExceptionHandle(e);
}
Session[_SessionSelected] = selectedValues;
GridViewModel viewModel = GridViewExtension.GetViewModel(str_GridViewName);
if (viewModel == null)
viewModel = CreateGridViewModelWithSummary();
string _FilterExpression = "";
int FILTER_UserID = usr.users_ID;
if (Session["myGridStatefiltrKM"] != null)
{
var userFiltersList = iMagoDataProvider.wusr_f_GetUserFiters(FILTER_UserID, "GridView_mpid_" + menu_pozycje_ID).Where(x => x.wusr_GrdFiltMenForSessionidId == Convert.ToInt32(Session["myGridStatefiltrKM"])).ToList().OrderByDescending(m => m.DomyslnyFiltr).ThenByDescending(m => m.DateCreated);
foreach (var item in userFiltersList)
{
_FilterExpression = item.FilterExpression.ToString();
}
}
if (_FilterExpression != "")
viewModel.FilterExpression = _FilterExpression;//"StartsWith([SymKar], 'aa')";
return AdvancedCustomBindingCore(viewModel);
}
// Paging
public ActionResult AdvancedCustomBindingPagingAction(GridViewPagerState pager)
{
int menu_pozycje_ID = System.Convert.ToInt32(Session[SessionEl.SESSION_MENU_ACT]);
UserDBModel usr = (UserDBModel)Session[SessionEl.SESSION_USER];
long _Session = System.Convert.ToInt64(usr.UserSessionID);
try
{
SortedList<string, model_Uprawnienia> rights = db.getPrawa(_Session, menu_pozycje_ID); ViewBag.Rights = rights;
}
catch (Exception e)
{
return ExceptionHandle(e);
}
var viewModel = GridViewExtension.GetViewModel(str_GridViewName);
viewModel.ApplyPagingState(pager);
string _FilterExpression = "";
try
{
db.wusr_p_GetGridFilterMenuForUsers(_Session, menu_pozycje_ID, str_GridViewName, ref _FilterExpression);//Pamietaj o wpisaniu prawidlowej nazwy dla grida(unikatowego w obrebie menu)
}
catch (Exception e)
{
return ExceptionHandle(e);
}
if (_FilterExpression != "")
{
viewModel.FilterExpression = _FilterExpression;//"StartsWith([SymKar], 'aa')";
}
if (Session["fulltextsearch"] == null)
{
//var model = iMagoDataProvider.Get_f_ListaZgloszen(userSessionid, 1);
Session["fulltextsearch"] = null;
return AdvancedCustomBindingCore(viewModel);
// return PartialView("Lista", model);
}
else
{
if (Session["filtr"] != null)
{
viewModel.FilterExpression = Session["filtr"].ToString();
}
var model = Session["fulltextsearch"];
return AdvancedCustomBindingCore(viewModel);
}
// return AdvancedCustomBindingCore(viewModel);
}
// Filtering
public ActionResult AdvancedCustomBindingFilteringAction(GridViewFilteringState filteringState)
{
int menu_pozycje_ID = System.Convert.ToInt32(Session[SessionEl.SESSION_MENU_ACT]);
UserDBModel usr = (UserDBModel)Session[SessionEl.SESSION_USER];
long _Session = System.Convert.ToInt64(usr.UserSessionID);
try
{
SortedList<string, model_Uprawnienia> rights = db.getPrawa(_Session, menu_pozycje_ID); ViewBag.Rights = rights;
}
catch (Exception e)
{
return ExceptionHandle(e);
}
var viewModel = GridViewExtension.GetViewModel(str_GridViewName);
viewModel.ApplyFilteringState(filteringState);
//Zapamietujemy filtry - na okres sessji ... pozniej odczytujemy ogolne tak by przy nowej sesji zawsze byly domyslne
int FILTER_UserID = usr.users_ID;
string _FilterExpression = "";
if (Session["myGridStatefiltrKM"] != null)
{
var userFiltersList = iMagoDataProvider.wusr_f_GetUserFiters(FILTER_UserID, "GridView_mpid_" + menu_pozycje_ID).Where(x => x.wusr_GrdFiltMenForSessionidId == Convert.ToInt32(Session["myGridStatefiltrKM"])).ToList().OrderByDescending(m => m.DomyslnyFiltr).ThenByDescending(m => m.DateCreated);
foreach (var item in userFiltersList)
{
_FilterExpression = item.FilterExpression.ToString();
}
}
return AdvancedCustomBindingCore(viewModel);
}
// Sorting
public ActionResult AdvancedCustomBindingSortingAction(GridViewColumnState column, bool reset)
{
int menu_pozycje_ID = System.Convert.ToInt32(Session[SessionEl.SESSION_MENU_ACT]);
UserDBModel usr = (UserDBModel)Session[SessionEl.SESSION_USER];
long _Session = System.Convert.ToInt64(usr.UserSessionID);
try
{
SortedList<string, model_Uprawnienia> rights = db.getPrawa(_Session, menu_pozycje_ID); ViewBag.Rights = rights;
}
catch (Exception e)
{
return ExceptionHandle(e);
}
var viewModel = GridViewExtension.GetViewModel(str_GridViewName);
viewModel.ApplySortingState(column, reset);
return AdvancedCustomBindingCore(viewModel);
}
// Grouping
public ActionResult AdvancedCustomBindingGroupingAction(GridViewColumnState column)
{
int menu_pozycje_ID = System.Convert.ToInt32(Session[SessionEl.SESSION_MENU_ACT]);
UserDBModel usr = (UserDBModel)Session[SessionEl.SESSION_USER];
long _Session = System.Convert.ToInt64(usr.UserSessionID);
try
{
SortedList<string, model_Uprawnienia> rights = db.getPrawa(_Session, menu_pozycje_ID); ViewBag.Rights = rights;
}
catch (Exception e)
{
return ExceptionHandle(e);
}
var viewModel = GridViewExtension.GetViewModel(str_GridViewName);
viewModel.ApplyGroupingState(column);
return AdvancedCustomBindingCore(viewModel);
}
Partial View
[HTML]
@{
SortedList<string, IMago.Models.model_Uprawnienia> rights = ViewBag.Rights;
}
@Html.DevExpress().GridView(
settings =>
{
settings.Name = "GridView_mgKar";
settings.CallbackRouteValues = new { Controller = "KartotekaMaterialowa", Action = "GridViewMgKarPartial" };
if (PageHelper.isVisible(rights, "GridView_mgKar_Grid_Oper_Filtr"))
settings.CustomBindingRouteValuesCollection.Add(
GridViewOperationType.Filtering,
new { Controller = "KartotekaMaterialowa", Action = "AdvancedCustomBindingFilteringAction" }
);
if (PageHelper.isVisible(rights, "GridView_mgKar_Grid_Oper_Group"))
settings.CustomBindingRouteValuesCollection.Add(
GridViewOperationType.Grouping,
new { Controller = "KartotekaMaterialowa", Action = "AdvancedCustomBindingGroupingAction" }
);
settings.Width = System.Web.UI.WebControls.Unit.Percentage(100);
settings.KeyFieldName = "SymKar;LogoP;JM;SymWL";
settings.SettingsPager.Visible = true;
settings.Settings.ShowGroupPanel = true;
settings.Settings.ShowFilterRow = true;
settings.SettingsBehavior.AllowSelectByRowClick = false;
settings.Settings.ShowFilterBar = GridViewStatusBarMode.Visible;
settings.Settings.ShowFooter = true;
settings.SettingsSearchPanel.Visible = false;
settings.Settings.ShowFilterRowMenuLikeItem = true;
settings.Settings.ShowHeaderFilterButton = true;
settings.EnableRowsCache = false;
settings.Styles.AlternatingRow.Enabled = DefaultBoolean.True;
settings.Styles.AlternatingRow.BackColor = System.Drawing.Color.White;
settings.Styles.Row.BackColor = System.Drawing.Color.WhiteSmoke;
settings.Styles.FocusedRow.CssClass = "EmptyFocusedRow";
settings.Styles.RowHotTrack.CssClass = "RowHover";
settings.Styles.Cell.Wrap = DefaultBoolean.False;
settings.Styles.Cell.Font.Size = FontUnit.Smaller;
settings.Styles.Header.Font.Size = FontUnit.XSmall;
settings.Styles.Header.Font.Bold = true;
if (PageHelper.isVisible(rights, "GridView_mgKar_Kol_SymKar"))
settings.Columns.Add(c =>
{
c.FieldName = "SymKar";
c.Settings.AutoFilterCondition = AutoFilterCondition.Contains;
c.Caption = IMago.Models.ResourcesModel.GetRes("TytulKolSymKar").ToUpper();
});
if (PageHelper.isVisible(rights, "GridView_Nag_Kol_pd_isstandard")) //Przy ZPW
settings.Columns.Add(column =>
{
column.FieldName = "pd_isstandard";
column.Caption = IMago.Models.ResourcesModel.GetRes("TytulKolpd_isstandard").ToUpper();
column.Width = 20;
column.HeaderStyle.Wrap = DefaultBoolean.True;
column.ColumnType = MVCxGridViewColumnType.CheckBox;
column.ReadOnly = true;
//column.PropertiesEdit.DisplayFormatString = "c";
column.UnboundType = DevExpress.Data.UnboundColumnType.Integer;
});
if (PageHelper.isVisible(rights, "GridView_mgKar_Kol_SymKarObcy"))
settings.Columns.Add(c =>
{
c.FieldName = "SymKarObcy";
c.Settings.AutoFilterCondition = AutoFilterCondition.Contains;
c.Caption = IMago.Models.ResourcesModel.GetRes("TytulKolSymKarObcy").ToUpper();
});
if (PageHelper.isVisible(rights, "GridView_mgKar_Kol_OpiKar"))
settings.Columns.Add(c =>
{
c.FieldName = "OpiKar";
c.Settings.AutoFilterCondition = AutoFilterCondition.Contains;
c.Caption = IMago.Models.ResourcesModel.GetRes("TytulKolOpikar").ToUpper();
});
if (PageHelper.isVisible(rights, "GridView_mgKar_Kol_L_OpiKar_EN"))
settings.Columns.Add(c =>
{
c.FieldName = "L_OpiKar_EN";
c.Settings.AutoFilterCondition = AutoFilterCondition.Contains;
c.Caption = IMago.Models.ResourcesModel.GetRes("TytulKolOpikarEn").ToUpper();
});
if (PageHelper.isVisible(rights, "GridView_mgKar_Kol_JM"))
settings.Columns.Add(c =>
{
c.FieldName = "JM";
c.Settings.AutoFilterCondition = AutoFilterCondition.Contains;
c.Caption = IMago.Models.ResourcesModel.GetRes("TytulKolJM").ToUpper();
c.Width = 50;
});
if (PageHelper.isVisible(rights, "GridView_mgKar_Kol_CenaNetto"))
settings.Columns.Add(c =>
{
c.FieldName = "CenaNetto";
c.Settings.AutoFilterCondition = AutoFilterCondition.Contains;
c.Caption = IMago.Models.ResourcesModel.GetRes("TytulKolCenaNetto").ToUpper();
c.PropertiesEdit.DisplayFormatString = PageHelper.N2_Format;
});
if (PageHelper.isVisible(rights, "GridView_mgKar_Kol_SymWL"))
settings.Columns.Add(c =>
{
c.FieldName = "SymWL";
c.Settings.AutoFilterCondition = AutoFilterCondition.Contains;
c.Caption = IMago.Models.ResourcesModel.GetRes("TytulKolSymWL").ToUpper();
});
if (PageHelper.isVisible(rights, "GridView_mgKar_Kol_IloscPAL"))
settings.Columns.Add(c =>
{
c.FieldName = "IloscPAL";
c.Settings.AutoFilterCondition = AutoFilterCondition.Contains;
c.Caption = IMago.Models.ResourcesModel.GetRes("TytulKolIloscCalopaletowa").ToUpper();
c.Width = 50;
c.PropertiesEdit.DisplayFormatString = PageHelper.N0_Format;
});
if (PageHelper.isVisible(rights, "GridView_mgKar_Kol_StanDys"))
settings.Columns.Add(c =>
{
c.FieldName = "StanDys";
c.Settings.AutoFilterCondition = AutoFilterCondition.Contains;
c.Caption = IMago.Models.ResourcesModel.GetRes("TytulKolStanWolny").ToUpper();
c.Width = 50;
c.PropertiesEdit.DisplayFormatString = PageHelper.N0_Format;
});
if (PageHelper.isVisible(rights, "GridView_mgKar_Kol_GruKar"))
settings.Columns.Add(c =>
{
c.FieldName = "GruKar";
c.Settings.AutoFilterCondition = AutoFilterCondition.Contains;
c.Caption = IMago.Models.ResourcesModel.GetRes("TytulKolSymKarGrup").ToUpper();
});
if (PageHelper.isVisible(rights, "GridView_mgKar_Kol_Waga"))
settings.Columns.Add(c =>
{
c.FieldName = "Waga";
c.Settings.AutoFilterCondition = AutoFilterCondition.Contains;
c.Caption = IMago.Models.ResourcesModel.GetRes("TytulKolWaga").ToUpper();
c.Width = 50;
c.PropertiesEdit.DisplayFormatString = PageHelper.N3_Format;
});
if (PageHelper.isVisible(rights, "GridView_mgKar_Kol_LogoP"))
settings.Columns.Add(c =>
{
c.FieldName = "LogoP";
c.Settings.AutoFilterCondition = AutoFilterCondition.Contains;
c.Caption = IMago.Models.ResourcesModel.GetRes("TytulKolLogoP").ToUpper();
// c.PropertiesEdit.DisplayFormatString = PageHelper.N3_Format
});
if (PageHelper.isVisible(rights, "GridView_mgKar_Kol_RodzajHandlowy"))
settings.Columns.Add(c =>
{
c.FieldName = "RodzajHandlowy";
c.Settings.AutoFilterCondition = AutoFilterCondition.Contains;
c.Caption = IMago.Models.ResourcesModel.GetRes("TytulKolRodzajHandlowy").ToUpper();
// c.PropertiesEdit.DisplayFormatString = PageHelper.N3_Format
});
if (PageHelper.isVisible(rights, "GridView_mgKar_Grid_Oper_Sort"))
settings.CustomBindingRouteValuesCollection.Add(
GridViewOperationType.Sorting,
new { Controller = "KartotekaMaterialowa", Action = "AdvancedCustomBindingSortingAction" }
);
settings.CustomBindingRouteValuesCollection.Add(
GridViewOperationType.Paging,
new { Controller = "KartotekaMaterialowa", Action = "AdvancedCustomBindingPagingAction" }
);
settings.EnableCallbackAnimation = false;
settings.CommandColumn.Visible = true;
settings.CommandColumn.ShowSelectCheckbox = true;
settings.CommandColumn.Width = Unit.Pixel(65);
settings.SettingsBehavior.ConfirmDelete = true;
settings.SettingsBehavior.AllowFocusedRow = true;
settings.ClientSideEvents.SelectionChanged = "OnSelectionChanged";
settings.ClientSideEvents.EndCallback = "OnEndCallback";
settings.CustomJSProperties = (sender, e) =>
{
e.Properties["cpFilterExpression"] = (sender as MVCxGridView).FilterExpression;
MVCxGridView g = sender as MVCxGridView;
Dictionary<int, object> dict = new Dictionary<int, object>();
int startIndex = g.PageIndex * g.SettingsPager.PageSize;
int endIndex = startIndex + g.SettingsPager.PageSize;
int kluczpomocny = 0;
for (int i = startIndex; i < endIndex; i++)
{
string klucz = g.GetRowValues(i, "SymKar") + "|" + g.GetRowValues(i, "LogoP") + "|" + g.GetRowValues(i, "JM") + "|" + g.GetRowValues(i, "SymWL");
dict[kluczpomocny] = klucz + "<|>" + g.GetRowValues(i, "LogoP") + "<|>" + g.GetRowValues(i, "JM") + "<|>" + g.GetRowValues(i, "SymWL") + "<|>" + g.GetRowValues(i, "CenaNetto")+"<|>"+ g.GetRowValues(i, "SymKar");
kluczpomocny++;
}
e.Properties["cpData"]=dict;
};
}).BindToCustomData(Model).GetHtml()
official reply from DevExpress: "Thank you for the sample project and database backup. I was able to reproduce both issues on my side. I also analyzed how your data layer works when this behavior is reproducible and now I see what causes the issue: you are placing an IQueriable model instance in a static field which is shared among different requests.
As far as I understand, you used the code for the helper class from our Custom Data Binding (Advanced) demo. In this demo, the data source can't be different: a query is always executed on the non-parameterized Emails data set. That's why we put it in a static property.
In your case, the static Model property will not work correctly for multiple concurrent requests. On each request, you are changing an IQueriable instance to a user-specific parameterized query. Due to the fact that an IQueriable instance uses the lazy-loading feature, a query is only executed when the ToList method is invoked (it is done internally in the GridView extension code). That's why you may encounter a situation when the following scenario occurs: you set a model for Grid1 and start building a database query in the GetDataAdvanced method, but at that time, Grid2 set its own model. Thus, substituting the model (the parameterized query to a stored procedure) of the first SQL query built by Grid1.
To fix this issue, I suggest that you make the GridViewCustomBindingHandlers class non-static and create an instance of this class for each controller. This will resolve the issue with the same data for two different users. Make sure that the 'MultipleActiveResultSets' parameter in the connection string is set to 'True'. I demonstrated the implementation of this approach in the updated sample project in the attachment.
Regarding the code in our demo: I described why we implemented it in this way above. However, our implementation in the demo made you implement your own data layer incorrectly. As we try to show the best practices in our demos, the fact that our implementation caused confusion did not go unnoticed. I passed the information regarding your scenario to the team for discussion. This will help us implement better demos/examples in the future or update the existing ones."