【问题标题】:Upon App Deployment, Controller Actions keep failing for Null Reference Exception?应用部署后,控制器操作因空引用异常而不断失败?
【发布时间】:2015-07-09 20:01:35
【问题描述】:

我有一个相当简单的 MVC5 应用程序,它带有一个 Oracle 后端,它在 Localhost 上运行良好,但在发布到内部服务器时有一些奇怪的行为。起初,我得到了一个直截了当的 500 - Internal Server Error,我通过尝试直接从服务器内访问该站点来诊断它。出于某种原因,在发布后,我的 Web.Config 正在添加第二个容器。

发布前呈现:

  <membership>
      <providers>
          <remove name="OracleMemberShipProvider"/>
      </providers>
  </membership>
  ....
  <customErrors mode="Off"/>
  ...

发布后:

  <membership>
      <providers>
          <remove name="OracleMemberShipProvider"/>
      </providers>
  </membership>
  //....
  <customErrors mode="Off"/>
  <membership>
      <providers>
          <clear />
      </providers>
  </membership>

我不确定为什么现在会出现这种情况(以前没有),但我可以通过在发布完成后登录服务器并从中删除重复的 来解决这个问题Web.Config

通过上述更正,我可以成功加载我的应用程序的主页视图。但是,如果我单击按钮导航到任何简单的控制器操作(编辑/创建/删除),我会收到:Server Error in '/' Applicaiton. Object reference not set to an instance of an object. 示例包括:

  • //projectRedirect/MY_CONTROLLER/Edit/78
  • //projectRedirect/MY_CONTROLLER/创建
  • //projectRedirect/MY_CONTROLLER/删除

由于Delete是最简单的,下面我将详细介绍:

    // GET: MY_Controller/Delete/5
    public async Task<ActionResult> Delete(int? id)
    {
        // Save the current URL (with any Filter Conditions) to return user after operation completes.
        Session["returnURL"] = Request.UrlReferrer.AbsoluteUri;

        if (id == null)
        {
            return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
        }
        MY_MODEL my_Model = await db.MY_MODEL.FindAsync(id);
        if (my_Model == null)
        {
            return HttpNotFound();
        }
        // Set property [OWNER] (ex.) 4 as [OWNER_NAME] (ex.) "SMITH, BOB" - cannot specify on the Grid Component, have to do in Controller.
        my_Model.OWNER = my_Model.Owner_Name;
        return View(my_Model);
    }

    // POST: MY_Controller/Delete/5
    [HttpPost]
    [ValidateAntiForgeryToken]
    public async Task<ActionResult> Delete(int id)
    {
        MY_MODEL my_Model = await db.MY_MODEL.FindAsync(id);
        db.MY_MODEL.Remove(my_Model);
        await db.SaveChangesAsync();
        // return RedirectToAction("Index", "Home");
        var returnURL = (Session["returnURL"] != null) ? Session["returnURL"].ToString() : Url.Action("Index", "Home");
        return Redirect(returnURL);
    }

我曾假设以下代码行可能是罪魁祸首(尽管之前没有问题)。它只是存储用户当前拥有的 URL(可以为指定的数据网格设置过滤条件):

// Save the current URL (with any Filter Conditions) to return user after operation is completed.
Session["returnURL"] = Request.UrlReferrer.AbsoluteUri;

在这种情况下,我的所有相关操作中都存在这一行。我尝试将其删除,但在再次进行 Publish/Web.Config 修改时,尝试导航到任何操作方法时仍然收到错误消息,但包含有关源错误的更多信息:

  • 删除 - 在我的 @using (Html.BeginForm()) { .... } 中找到标志 @Html.AntiForgeryToken()
  • 创建 - 标志 @Html.ValidationMessageFor(Model =&gt; model.FIELD8, "", new { @class = "text-danger" })
  • 编辑 - 标志@htmal.TextBoxFor(model =&gt; model.FIELD16, new { @class = "form-control", @readonly = "readonly" })

下面是我提供的堆栈跟踪,试图移动到我的 DELETE 视图:

[NullReferenceException: Object reference not set to an instance of an object.]
   Project.Controllers.<Delete>d__29.MoveNext() +163
   System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) +144
   System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) +84
   System.Web.Mvc.Async.TaskAsyncActionDescriptor.EndExecute(IAsyncResult asyncResult) +143
   System.Web.Mvc.Async.<>c__DisplayClass37.<BeginInvokeAsynchronousActionMethod>b__36(IAsyncResult asyncResult) +23
   System.Web.Mvc.Async.AsyncInvocationWithFilters.<InvokeActionMethodFilterAsynchronouslyRecursive>b__3d() +112
   System.Web.Mvc.Async.<>c__DisplayClass46.<InvokeActionMethodFilterAsynchronouslyRecursive>b__3f() +452
   System.Web.Mvc.Async.<>c__DisplayClass33.<BeginInvokeActionMethodWithFilters>b__32(IAsyncResult asyncResult) +15
   System.Web.Mvc.Async.<>c__DisplayClass2b.<BeginInvokeAction>b__1c() +32
   System.Web.Mvc.Async.<>c__DisplayClass21.<BeginInvokeAction>b__1e(IAsyncResult asyncResult) +231
   System.Web.Mvc.Controller.<BeginExecuteCore>b__1d(IAsyncResult asyncResult, ExecuteCoreState innerState) +29
   System.Web.Mvc.Async.WrappedAsyncVoid`1.CallEndDelegate(IAsyncResult asyncResult) +111
   System.Web.Mvc.Controller.EndExecuteCore(IAsyncResult asyncResult) +53
   System.Web.Mvc.Async.WrappedAsyncVoid`1.CallEndDelegate(IAsyncResult asyncResult) +19
   System.Web.Mvc.MvcHandler.<BeginProcessRequest>b__5(IAsyncResult asyncResult, ProcessRequestState innerState) +51
   System.Web.Mvc.Async.WrappedAsyncVoid`1.CallEndDelegate(IAsyncResult asyncResult) +111
   System.Web.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +606
   System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +288

有人知道如何解决这个问题吗?我已经彻底绞尽脑汁,但不知道为什么会突然发生这种情况或如何解决它。


编辑

所以经过大量测试,我现在有了一些新信息(但没有真正的答案)。我仍然不知道的事情:

  • 为什么额外的 >membership 在发布时被添加到我的 Web.Config(烦人,但可以在发布后在服务器上修改以修复)。

关于新信息,我已确认所有其他发布的问题似乎都与我对会话变量的使用有关。

  • 当我在我的编辑/删除/创建控制器操作中取消注释以下代码行时 - Session["returnURL"] = Request.UrlReferrer.AbsoluteUri; - 在尝试加载我的任何编辑/删除/创建视图时,如前所述,我会得到一个平面 Server Error in '/' Application. Object reference not set to an instance of an object
  • 调查我的视图,我发现如果我还从下面的代码段中注释掉每个视图的以下内容 - @*&lt;a href="@Session["returnURL"].ToString()"&gt;&lt;span class="btn btn-default"&gt;Back to List&lt;/span&gt;&lt;/a&gt;*@ - 我的所有视图都会加载:

    <div class="form-group">
        <div class="col-md-offset-2 col-md-10">
            @*@Html.ActionLink("Back to List", "Index", new { controller = "Home" }, new { @class = "btn btn-default" })*@ 
            @*<a href="@Session["returnURL"].ToString()"><span class="btn btn-default">Back to List</span></a>*@ |
            <input type="submit" value="Save" class="btn btn-primary" />
        </div>
    </div>
    

是否有人认为我的已发布服务器不喜欢我使用此 Session 变量(但 localhost 处理得很好)或我可以尝试的替代工作?此特定值对于确保在操作完成后将我的用户返回到主视图的 URL 很重要(在数据网格的 URL 中指定了任何/所有指定的过滤)。

【问题讨论】:

    标签: c# asp.net-mvc razor asp.net-mvc-5


    【解决方案1】:

    我终于找到了一些答案。首先,我发现在应用部署后我在Web.config 中获得了额外的代码,因为为Web.Release.Config 指定了一些Insert 代码:

        <!--<membership xdt:Transform="Insert">
          <providers>
            <clear/>
          </providers>
        </membership>
        <roleManager xdt:Transform="Insert">
          <providers>
            <clear/>
          </providers>
        </roleManager>-->
    

    已注释掉插入内容,现在无需在发布后手动修改Web.config

    接下来,当我尝试访问我的Session["variables"] 时,我在这篇帖子 (The Session object is null in ASP.NET MVC 4 webapplication once deployed to IIS 7 (W 2008 R2)) 中找到了接收NullReferenceException 的答案;我只是修改了我的&lt;modules&gt; 部分以执行以下指定值的add/remove

      <configuration>
      ...
      <system.webServer>
        ...
        <modules>
          <remove name="Session" />
          <add name="Session" type="System.Web.SessionState.SessionStateModule"/>
          ...
        </modules>
      </system.webServer>
    </configuration>
    

    我仍然不完全确定为什么这是答案,但在这种情况下它适用于我的问题。

    【讨论】:

      【解决方案2】:

      NullReferenceException 是一个运行时错误,通常与意外解析为 null 的类实例有关。

      发布的代码中没有任何内容可能是罪魁祸首,但错误可能出现在您的视图、子操作、布局等中。仅仅因为它发生在 Delete 操作的运行期间不会'并不意味着它一定是 in 那个动作。这只是意味着在此操作返回结果的过程中运行的一些代码会引发此异常。不幸的是,异步的缺点之一是它往往会掩盖问题的根源,尤其是对于运行时错误。

      查找您正在查询数据库、使用可为空值类型(int?、string 等)或从 ViewBagSession 之类的动态中解析某些内容的实例。同样,您在发布的代码中使用 Session 很好,因为您在那里进行了适当的空值检查,但在其他地方可能还有其他一些您没有的情况。

      【讨论】:

      • 感谢克里斯的回复(以及一如既往的深思熟虑的答案)。我在上面的编辑中发布了更多信息;似乎所有问题都围绕着我的 Session 变量?
      猜你喜欢
      • 1970-01-01
      • 2018-01-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-02-06
      • 2022-08-13
      • 1970-01-01
      • 2019-09-09
      相关资源
      最近更新 更多