为什么 Asp.net MVC4 不能使用 SQL Server Session 状态存储的 cookieless

Why Asp.net MVC4 can not use the cookieless of SQL Server Session state storage

ALL,这是我在 Asp.net MVC4 应用程序中的 Web 配置。我发现如果我设置 cookieless false ,一切都很好。但如果我不想使用 cookie 。然后应用程序无法工作。当我调试应用程序时,我发现控制器无法接收来自视图的任何请求。我认为这是因为在无 cookie 模式下,Something 会附加到 url before 。像 http://localhost:8119/(S(3cicpjpagvpunr5he5fnfrj1))/.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
<configuration>
  <configSections>
    <sectionGroup name="system.web.webPages.razor" type="System.Web.WebPages.Razor.Configuration.RazorWebSectionGroup, System.Web.WebPages.Razor, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35">
      <section name="webAssets" type="Telerik.Web.Mvc.Configuration.WebAssetConfigurationSection, Telerik.Web.Mvc" requirePermission="false" />
      <!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 -->
      <section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=4.4.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
    </sectionGroup>
  </configSections>

  <connectionStrings>
   
  </connectionStrings>
 
   
   
   
   
   
  </appSettings>
  <system.web>
    <customErrors mode="Off" />
    <httpRuntime executionTimeout="14400" maxRequestLength="716800" />
    <compilation debug="true" targetFramework="4.0" />
   
      <forms loginUrl="~/Account/Login" timeout="2880" />
    </authentication>
    <pages>
      <namespaces>
       
       
       
       
       
       
       
      </namespaces>
    </pages>
    <profile defaultProvider="DefaultProfileProvider">
      <providers>
       
      </providers>
    </profile>
    <membership defaultProvider="DefaultMembershipProvider">
      <providers>
       
      </providers>
    </membership>
    <roleManager defaultProvider="DefaultRoleProvider">
      <providers>
       
      </providers>
    </roleManager>
    <!-- <sessionState mode="InProc" timeout="30" customProvider="DefaultSessionProvider">
      <providers>
       
      </providers>
    </sessionState> -->
    <sessionState mode="SQLServer" cookieless="true" sqlConnectionString="data source=xxxx; User ID=xxxx; password=xxxx" timeout="300" sqlCommandTimeout="10" />
    <httpHandlers>
     
    </httpHandlers>
  </system.web>
  <system.webServer>
    <security>
      <requestFiltering>
        <requestLimits maxAllowedContentLength="3000000000" />
      </requestFiltering>
    </security>
    <validation validateIntegratedModeConfiguration="false" />
    <modules runAllManagedModulesForAllRequests="true" />
    <directoryBrowse enabled="true" />
    <handlers>
      <remove name="asset" />
     
    </handlers>
  </system.webServer>
  <runtime>
   
      <dependentAssembly>
       
        <bindingRedirect oldVersion="1.0.0.0-2.0.0.0" newVersion="2.0.0.0" />
      </dependentAssembly>
      <dependentAssembly>
       
        <bindingRedirect oldVersion="0.0.0.0-4.0.0.0" newVersion="4.0.0.0" />
      </dependentAssembly>
      <dependentAssembly>
       
        <bindingRedirect oldVersion="0.0.0.0-2.0.0.0" newVersion="2.0.0.0" />
      </dependentAssembly>
      <dependentAssembly>
       
        <bindingRedirect oldVersion="0.0.0.0-1.7.0.0" newVersion="1.7.0.0" />
      </dependentAssembly>
    </assemblyBinding>
  </runtime>
 </configuration>

cookieless="true" 一起使用时,Html.BeginForm() 助手(不带任何参数的助手)中有一个错误。生成 url 时不考虑 session id。所以代替:

1
<form action="/(S(kkt0zgbnuaoxad23ew33iod4))/home/index" method="post">

它生成:

1
<form action="/home/index" method="post">

当您发布到 /home/index 时,ASP.NET 会自动重定向到 /(S(kkt0zgbnuaoxad23ew33iod4))。重定向意味着 GET 请求 => 您的 POST 操作将永远不会被命中。

作为一种解决方法,您可以编写自定义 Html.BeginForm 帮助程序来修复错误:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public static class FormExtensions
{
    public static IDisposable MyBeginForm(this HtmlHelper htmlHelper)
    {
        var rawUrl = htmlHelper.ViewContext.HttpContext.Request.RawUrl;
        var formAction = htmlHelper.ViewContext.HttpContext.Response.ApplyAppPathModifier("~/") + rawUrl;
        var builder = new TagBuilder("form");
        builder.MergeAttributes(new RouteValueDictionary());
        builder.MergeAttribute("action", formAction);
        builder.MergeAttribute("method", HtmlHelper.GetFormMethodString(FormMethod.Post), true);
        htmlHelper.ViewContext.Writer.Write(builder.ToString(TagRenderMode.StartTag));
        var form = new MvcForm(htmlHelper.ViewContext);
        return form;
    }
}

然后使用:

1
2
3
4
@using (Html.MyBeginForm())
{
    ...
}

就 BeginForm 助手的其他重载而言,它们应该可以正常工作并生成包含会话 ID 的正确操作。