c# - 为什么在 Controller 上设置了 SessionStateBehavior.ReadOnly 后我仍然可以写入 session ,我应该关心吗?

标签 c# .net asp.net-mvc-4 session-state

我有许多 Controller ,在它们上面设置了 SessionStateBehavior.ReadOnly 以启用多个 ajax 请求的并行处理。

但我注意到这并没有阻止我写入 session (不像 SessionStateBehavior.Disabled 会引发异常)。

我的应用程序使用 Microsoft Charting,图表和图像映射是响应 ajax 请求生成的,图表存储在 session 中,直到浏览器呈现图像标记,此时图像 src 触发浏览器请求从 session 中检索的图表图像。因此,在写入 session 之前尝试读取 session 没有问题。

一切正常,我有多个并行处理的 ajax 请求,我的图表被正确返回,所以我在写入 session 时声明 SessionStateBehavior.ReadOnly 是否重要?

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Web.Mvc;
using System.Web.UI.DataVisualization.Charting;
using Mdl.Rcm.Web.Areas.Dashboards.Models;
using Mdl.Web.Security;
using Mdl.Persistence.UoW;
using Mdl.Rcm.Business.Dashboards;
using Mdl.Rcm.Business.Dashboards.Models;
using Mdl.Rcm.Web.Areas.Dashboards.Charts;
using Mdl.Rcm.Web.Areas.Dashboards.Charts.OrganisationConnectionsByRole;
using Mdl.Web.Mvc;

namespace Mdl.Rcm.Web.Areas.Dashboards.Controllers
{
    /// <summary>
    /// Controller for the Organisation Connections By Role chart.
    /// </summary>
    [SessionState(System.Web.SessionState.SessionStateBehavior.ReadOnly)]
    [RedirectingAuthorize(Roles = "Dashboards")]
    [Area(IsSiteRoot = false)]
    public class ChartOrganisationConnectionsByRoleController : Controller
    {
        private readonly IRelationshipAndRiskService relationshipAndRiskService;
        private readonly IConfigurationService configurationService;
        private readonly IOrganisationConnectionsByRoleChartBuilder chartBuilder;
        private readonly IListService listService;
        private BarConfiguration barConfiguration;
        private const string TempDataKey = "OrganisationConnectionsByRoleData";

        public ChartOrganisationConnectionsByRoleController(IOrganisationConnectionsByRoleChart organisationConnectionsByRoleChart, IRelationshipAndRiskService relationshipAndRiskService, IConfigurationService configurationService, IOrganisationConnectionsByRoleChartBuilder chartBuilder, IListService listService)
        {
            this.relationshipAndRiskService = relationshipAndRiskService;
            this.configurationService = configurationService;
            this.chartBuilder = chartBuilder;
            this.listService = listService;
        }

        /// <summary>
        /// Standard Organisation Connections by Role component loader
        /// </summary>
        /// <param name="listId">The list id.</param>
        /// <param name="degree">The active degree.</param>
        /// <param name="barIndex">Index of the active bar.</param>
        /// <returns></returns>
        [HandleAjaxError]
        public ActionResult Load(int listId, int degree, int barIndex)
        {
            using (UnitOfWork.Start("Analysis"))
            {
                // Get the data
                var relationshipPlanningData = GetChartDataForInitialLoadParentComponent(listId);

                var connectionsFound = relationshipPlanningData.SeriesModels.Count > 0;

                var listName = listService.GetListName(listId).Name;

                var information = new InformationModel(degree, true) { ConnectionsFound = connectionsFound, NumberOfOrganisationsInList = relationshipPlanningData.TotalNumberOfOrganisations, ListName = listName };

                return PartialView("OrganisationConnectionsByRoleComponent", new OrganisationConnectionsByRoleComponentModel { ListId = listId, ActiveDegree = degree, ActiveBarIndex = barIndex, BarConfiguration = configurationService.GetBarConfiguration(), ConnectionsFound = connectionsFound, Information = information});
            }
        }

        /// <summary>
        /// Creates the Connections by Role chart and stores it in Session then returns the chart map.
        /// The chart image map is always created first, the chart is created as part of the process of creating the map.
        /// </summary>
        /// <returns></returns>
        public ActionResult Chart(Guid chartId, int listId)
        {
            using (UnitOfWork.Start("Analysis"))
            {
                barConfiguration = configurationService.GetBarConfiguration();

                var relationshipPlanningData = GetChartDataForInitialLoadChart();

                if (relationshipPlanningData.SeriesModels.Count == 0)
                {
                    return PartialView("InfoMessage", "No connections found");
                }

                // Set up the chart
                return GenerateChart(relationshipPlanningData, listId, chartId);
            }
        }

        private ActionResult GenerateChart(OrganisationConnectionsByRoleData relationshipPlanningData, int listId, Guid chartId)
        {
            var chartAndXPoints = chartBuilder.BuildChart(2, relationshipPlanningData, barConfiguration, SetActiveBarIndex(-1), listId);

            // Store the chart in session for retrieval by the browser as the src on an image tag.
            ChartSession.GenerateChartToSession(chartId, chartAndXPoints.Chart, Session);

            // Get y data for use client side
            var yPointsDataView = GetYPointsDataView(relationshipPlanningData);

            // Get x co-ordinates for use client side. Must be done after the chart has been generated to session.
            var xPointsView = GetXPointsView(chartAndXPoints.XPoints);

            // Render the image tag and image map
            return this.Chart(chartAndXPoints.Chart, xPointsView + yPointsDataView, chartId, "ConnectionsByRoleImage");
        }

        /// <summary>
        /// Gets the chart data for use by the main component.
        /// </summary>
        /// <param name="listId">The list id.</param>
        /// <returns></returns>
        private OrganisationConnectionsByRoleData GetChartDataForInitialLoadParentComponent(int listId)
        {
            // This is the call from the load action so get the data and store it for use by the chart action to save the performance hit
            var data = relationshipAndRiskService.GetOrganisationConnectionsByRoleChartData(listId);
            TempData[TempDataKey] = data;

            return data;
        }

        /// <summary>
        /// Gets the chart data for use by the main component chart.
        /// </summary>
        /// <returns></returns>
        private OrganisationConnectionsByRoleData GetChartDataForInitialLoadChart()
        {
            // This call is from the chart action so use the data that was retreived on the load action
            return (OrganisationConnectionsByRoleData)TempData[TempDataKey];
        }

        /// <summary>
        /// Return the Connections By Role chart from session.
        /// </summary>
        /// <returns></returns>
        public ActionResult ConnectionsByRoleImage(Guid chartId)
        {
            var chart = ChartSession.GetChartFromSession(chartId, Session);
            return File(chart, "image");
        }

        /// <summary>
        /// Return the Connections By Role chart from session.
        /// </summary>
        /// <param name="listId">The list id.</param>
        /// <param name="degree">The active degree.</param>
        /// <param name="barIndex">Index of the active bar.</param>
        /// <returns></returns>
        public ActionResult ConnectionsByRoleActive(int listId, int degree, int barIndex)
        {
            using (UnitOfWork.Start("Analysis"))
            {
                barConfiguration = configurationService.GetBarConfiguration();

                // Get the data
                var relationshipPlanningData = relationshipAndRiskService.GetOrganisationConnectionsByRoleChartData(listId);

                if (relationshipPlanningData.SeriesModels.Count == 0)
                {
                    return PartialView("InfoMessage", "No connections found");
                }

                 // Set up the chart
                var chartAndXPoints = chartBuilder.BuildChart(SetActiveDegree(degree), relationshipPlanningData, barConfiguration, SetActiveBarIndex(-1), listId);

                var ms = new MemoryStream();
                chartAndXPoints.Chart.SaveImage(ms, ChartImageFormat.Png);

                return File(ms.ToArray(), "image");
            }
        }

        /// <summary>
        /// Gets the graph X points and render them as a javascript object for use by the view.
        /// </summary>
        /// <param name="xPoints">The x points.</param>
        /// <returns></returns>
        private string GetXPointsView(List<float> xPoints)
        {
            var model = new XPointsModel
            {
                ChartName = "Connections By Role",
                Points = xPoints
            };

            return this.ViewAsString("XPoints", model);
        }

        /// <summary>
        /// Gets the Y points data and render them as a javascript object for use by the view.
        /// </summary>
        /// <param name="relationshipPlanningData">The relationship planning data.</param>
        /// <returns></returns>
        private string GetYPointsDataView(OrganisationConnectionsByRoleData relationshipPlanningData)
        {
            var degree1DataPoints = relationshipPlanningData.SeriesModels[0].DataPoints.Select(p => p.Y).ToList();
            var degree2DataPoints = relationshipPlanningData.SeriesModels[1].DataPoints.Select(p => p.Y).ToList();

            var model = new YPointsDegree1And2Model
            {
                ChartName = "Connections By Role",

                Degree1Data = degree1DataPoints,
                Degree2Data = degree2DataPoints
            };

            return this.ViewAsString("YPointsDegree1And2", model);
        }

        private int SetActiveBarIndex(int barIndex)
        {
            if (barIndex == -1)
            {
                barIndex = barConfiguration.Bars.First(b => b.IsDefaultActive).Index;
            }
            return barIndex;
        }

        private static int SetActiveDegree(int degree)
        {
            if (degree == -1)
            {
                degree = 2;
            }
            return degree;
        }
    }
}

    public class ChartSession
    {
        public static byte[] GetChartFromSession(Guid chartId, HttpSessionStateBase session)
        {
             // Get the chart from session
            var data = session[chartId.ToString()] as byte[];

            // Clear the session
            session[chartId.ToString()] = null;

            return data;
        }

        public static void GenerateChartToSession(Guid chartId, Chart chart, HttpSessionStateBase session)
        {
            var ms = new MemoryStream();
            chart.SaveImage(ms, ChartImageFormat.Png);
            session[chartId.ToString()] = ms.ToArray();
        }

最佳答案

SessionStateBehavior 只告诉 ASP.NET 在 Session

上加什么锁

看到这个问题:Controller SessionStateBehavior is ReadOnly and I can update Session Variable

关于c# - 为什么在 Controller 上设置了 SessionStateBehavior.ReadOnly 后我仍然可以写入 session ,我应该关心吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14154653/

相关文章:

c# - 排序 ObservableCollection

c# - Azure Keyvault 本地问题

asp.net - 如何使用 Razor 链接到 ASP.NET MVC 4 中的文件?

c# - 在 WCF (C#) 中引用服务时出现问题

c# - 无法使用 LINQPad 4 更新行

c# - 在 C# 应用程序中查找命名互斥体

.net - Windows Mobile/Windows CE 上的服务器推送/HTTP 流

c# - 在 Asp.net mvc4 应用程序中显示 Html.DropDownList 中的两个字段

asp.net-mvc-4 - HTML.EditorFor不允许用户定义属性?

c# - 如何从我创建的消息框中返回是或否?