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

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

我的应用程序使用Microsoft Charting,并且响应于ajax请求而生成图表和图像 map ,并将图表存储在 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/

10-10 18:24