在应用程序部署时,控制器操作会因空引用异常而失败吗?

时间:2015-07-09 20:01:36

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

我有一个相当简单的MVC5应用程序,它有一个Oracle Backend,它在Localhost上运行良好,但在发布到内部服务器时有一些奇怪的行为。起初我得到了一个直接的 500 - 内部服务器错误,我通过尝试从服务器直接访问该站点来诊断。出于某种原因,在发布时我的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>

我不确定为什么现在这种情况很烦人(之前没有),但我已经能够通过在Publish完成后删除重复的 来自 Web.Config

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

  • // projectRedirect / MY_CONTROLLER /编辑/ 78
  • // projectRedirect / MY_CONTROLLER /创建
  • // projectRedirect / MY_CONTROLLER /删除

由于删除是最简单的,我将在下面详细说明:

    // 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修改时,我仍然在尝试导航到任何操作方法时收到错误,尽管有更多关于源错误的信息:

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

下面是我的Stack Trace,尝试移动到我的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

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

修改

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

  • 为什么在发布时将额外的&gt;成员资格&lt; 添加到我的Web.Config(烦人,但可以在发布后修改后修改服务器)。

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

  • 当我在编辑/删除/创建控制器操作 - Session["returnURL"] = Request.UrlReferrer.AbsoluteUri;中取消注释以下代码行时 - 在尝试加载任何编辑/删除操作时,我给出了前面提到的单Server Error in '/' Application. Object reference not set to an instance of an object /创建视图。
  • 调查我的观点,我发现我的所有观点都会加载,如果我还在下面的代码段中对每个观点进行评论 - @*<a href="@Session["returnURL"].ToString()"><span class="btn btn-default">Back to List</span></a>*@ -

    <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处理正常)或者我可以尝试的替代工作?这个特殊值对于确保在操作完成后确保我的用户返回到主View的URL(其中包含在数据网格的URL中指定的任何/所有指定的过滤)非常重要。

2 个答案:

答案 0 :(得分:1)

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

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

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

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

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

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

答案 1 :(得分:0)

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

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

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