【问题标题】:Javascript executing MVC code in If statement incorrectlyJavascript 在 If 语句中错误地执行 MVC 代码
【发布时间】:2012-10-24 12:01:19
【问题描述】:

我对下面的代码有点困惑。它在 Windows 7 上的 VS2010 中运行良好,现在我已经将硬件升级到 Windows 8 和 VS 2012,它没有。

我的 MVC 应用程序中有以下 JavaScript 代码:

<script language="javascript" type="text/javascript">
var today;

if("@Model.Birthday.HasValue"){
    var today = new Date("@Model.Birthday.Value.Year", "@Model.Birthday.Value.Month" - 1, "@Model.Birthday.Value.Day");
}else{
    today = new Date();
}

模型从具有如下属性的 ViewModel 中提取:

    public System.DateTime? Birthday
    {
        get { return user.Birthday; }
        set { user.Birthday = value; }
    }

该行抛出异常:

var today = new Date("@Model.Birthday.Value.Year", "@Model.Birthday.Value.Month" - 1, "@Model.Birthday.Value.Day");

它返回“Nullable object must have value”,如果它跳转到该行执行它应该。但是,我的 if 语句返回错误。如果我删除该行并只放入一个警报语句,它永远不会执行该行或显示警报,因为生日属性为空。 JS 执行 MVC 代码的方式似乎发生了一些变化,它似乎评估了整个代码块,而不管 if 语句如何。我也尝试了以下方法,但无济于事:

  • 在 Chrome for W8 中测试
  • 在 try / catch 块中测试。有趣的是,它并没有捕捉到异常(我猜 JS 不会捕捉到 .NET 异常)
  • 通过明确声明 @Model.Birthday.HasValue == true 进行测试
  • 已通过将其更改为 @Model.Birthday.Value != null 进行测试
  • 在发布模式而不是调试模式下测试

这应该很简单 - 测试一个值是否为 null,如果不是,则从 .NET 属性创建一个 JS Date 对象,如果是,则创建一个新的 JS Date 对象,但由于某种原因,它想要评估并执行那条线,即使 HasValue 是假的。

真的很难过。有人见过这样的吗?

【问题讨论】:

  • 您升级的是软件,而不是硬件。 (除非你换了机器。)
  • 嗯,从技术上讲,在升级软件时,我有一台新机器要开发,所以我确实升级了硬件和软件。无论如何,它在 IE 9 上的 VS2010 中运行没有问题,现在它失败了。

标签: javascript asp.net-mvc internet-explorer-10


【解决方案1】:

问题在于您混淆了客户端代码和服务器端代码。 javascript 在客户端运行,但只有在所有服务器端代码都完成之后。

所以@Model.Birthday.HasValue、@Model.Birthday.Value.Year 等都将在服务器端进行评估,然后再靠近浏览器。 javascript 代码(因此在这种情况下是 if 语句)永远不会到达浏览器,因为异常发生在服务器端,试图在 null 对象上评估 Model.Birthday.Value.Year。

您需要移动条件服务器端,例如

@if(Model.Birthday.HasValue){
    @:today = new Date(@(Model.Birthday.Value.Year), @(Model.Birthday.Value.Month) - 1, @(Model.Birthday.Value.Day));
} else {
    @:today = new Date();
}

【讨论】:

    【解决方案2】:

    我可以看到这里发生的一些事情会影响您呈现正确数据的能力。

    首先,MVC 变量在服务器端进行处理。您当前的实现总是尝试在您的 Javascript 中呈现 @Model.Birthday.Value 属性的值以生成 HTML。无论您当前示例中的属性是 true 还是 false,都会发生这种情况,因为它依赖于客户端 Javascript 来执行条件而不是 Razor。以下是您问题的完整工作示例。

    查看模型

    namespace MvcApplication1.Models
    {
        public class TestViewModel
        {
            public DateTime? NullDate { get; set; }
    
            public DateTime? DateWithValue { get; set; }
        }
    }
    

    控制器

    public ActionResult Index()
            {
                return View(new TestViewModel{DateWithValue = DateTime.Now, 
    NullDate = null});
                }
    

    查看

    @model MvcApplication1.Models.TestViewModel
    @{
        ViewBag.Title = "Index";
    }
    
    <h2>Index</h2>
    
    <script type="text/javascript">
        var today;
        var anotherDay;
    
        @{if(Model.NullDate.HasValue)
        {
            @: alert('Null date had a value!');
            @: today = new Date('@Model.NullDate.Value.Year', parseInt('@Model.DateWithValue.Value.Month') - 1, '@Model.NullDate.Value.Day');
        }else
          {
            @: alert('Null date did not have a value');
            @: today = new Date();
        }}
    
        @{if (Model.DateWithValue.HasValue)
          {
            @: alert('DateWithValue had a value!');
                @: anotherDay = new Date('@Model.DateWithValue.Value.Year', parseInt('@Model.DateWithValue.Value.Month') - 1, '@Model.DateWithValue.Value.Day');
              @: alert(anotherDay);
          }
          else
          {
              @: alert('DateWithValue date did not have a value');
            @: anotherDay = new Date();
        }}
    </script>
    

    现在显然,代码在 Javascript 部分中重复,以表明它适用于同一控制器操作中的空值和非空值。

    正如您在视图中看到的,我们确保使用 Razor 语法检查模型,使用 Javascript 设置实际的客户端变量。另外,我想知道您的“- 1”是否正常工作。为了在本例中进行减法运算,我必须将该值从 Javascript 转换为 Int,但这是一个小细节。

    作为参考,这是 VS2012 上的 MVC 4 项目,Windows 8 Professional 使用 Chrome 测试。

    【讨论】:

      【解决方案3】:

      简而言之解决方案:

      我测试了您的代码,可以说,您的硬件/软件更新没有问题。我在 Win 7 上运行 VS 2010。 解决方案可能是 例如以这种方式更改您的代码

      <script language="javascript" type="text/javascript">
      
                  @{ // C# server side part to get the dateParameters
                      var dateParameters = string.Empty;
                      if (Model.Birthday.HasValue)
                      {
                          dateParameters = "" + @Model.Birthday.Value.Year
                                       + ", " + (@Model.Birthday.Value.Month - 1)
                                       + ", " + @Model.Birthday.Value.Day;
                      }
                  }
                  // JS client side, later working with just created dateParameters 
                  var today = new Date(@dateParameters);
                  alert(today);
          </script>
      

      详细解释:

      要找到答案,让我们拆分上面的 sn-p 做什么。 只是呈现 HTML 代码。让我们一步一步来看看吧

      我。有值

      @Model.Birthday = new Date(2012,11,4)

      1) Razor 正在发送到响应流字符串,直到第一个 @ 运算符

      <script language="javascript" type="text/javascript">
      var today;
      
      if("
      

      2) 这里 Razor 评估这部分 @Model.Birthday.HasValue 作为布尔值并将其转换为字符串,因此代码的下一部分将是

      True
      

      3) 附加下一个直接字符串

      "){
          var today = new Date("
      

      4) 评估@Model.Birthday.Value.Year 并注入其字符串值

      2012
      

      5) 6) 7) ... 以此类推 发送给 Response 的最终结果是:

      <script language="javascript" type="text/javascript">
          var today;
      
          if ("True"){
              var today = new Date("2012", "11" - 1, "4");
          } else{
              today = new Date();
          }
      </script>
      

      二。生日为 NULL

      如果@Model.Birthday = null 第一步 1)、2) 和 3) 相同:

      <script language="javascript" type="text/javascript">
          var today;
      
          if ("True"){
              var today = new Date("
      

      4) 异常可空对象必须有值

      最后,我们得到了 Nullable 异常的地方。

      @Model.Birthday.Value.Year

      被调用

      @Model.Birthday == null

      【讨论】:

      • 完美。感谢您花时间详细说明回复。很有帮助。
      【解决方案4】:

      多行代码

      @if ( Model.SomeProp == true)
      {
        <text>
          <Your java script Multi-line  code>
        </text>
      }
      

      单行代码

      @if ( Model.SomeProp == true)
      {  
          @:<Your java script single-line code>  
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-04-04
        • 2015-02-26
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多