6

我有许多设置了 SessionStateBehavior.ReadOnly 的控制器,以启用多个 ajax 请求的并行处理。

但是我注意到这并不能阻止我写入会话(与 SessionStateBehavior.Disabled 不同,它会引发异常)。

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

一切正常,我有多个 ajax 请求被并行处理,并且我的图表被正确返回,所以我在写入会话时声明 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();
        }
4

1 回答 1

5

SessionStateBehavior只告诉 ASP.NET 在Session

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

于 2013-01-04T11:14:06.363 回答