javascript Javascript在If语句中错误地执行MVC代码

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/13218759/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-26 18:06:26  来源:igfitidea点击:

Javascript executing MVC code in If statement incorrectly

javascriptasp.net-mvcinternet-explorer-10

提问by Tyler Davey

I am a bit stumped with the following code. It worked fine in VS2010 on Windows 7, and now that I've upgraded the hardware to Windows 8 and VS 2012, it does not.

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

I have the following JavaScript code in my MVC application:

我的 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();
}

The Model is pulling from a ViewModel that has a property that looks like this:

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

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

The exception is thrown in the line:

在行中抛出异常:

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

It comes back with "Nullable object must have value", which it should if it jumps in that line to execute. But, my if statement is returning false. If I remove the line and just put in an alert statement, it never executes that line or shows the alert, because the Birthday property is null. Something seems to have shifted in how JS executes MVC code, and it seems to evaluate the entirety of the code block, regardless of the if statement. I've also tried the following, but to no avail:

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

  • Tested in Chrome for W8
  • Tested in a try / catch block. Interestingly, it doesn't catch the exception (I guess JS won't catch .NET exceptions)
  • Tested by explicitly stating @Model.Birthday.HasValue == true
  • Tested by changing it to @Model.Birthday.Value != null
  • Tested in Release mode over Debug Mode
  • 在适用于 W8 的 Chrome 中测试
  • 在 try / catch 块中测试。有趣的是,它不会捕获异常(我猜 JS 不会捕获 .NET 异常)
  • 通过显式声明 @Model.Birthday.HasValue == true 进行测试
  • 通过将其更改为 @Model.Birthday.Value != null 进行测试
  • 在发布模式下通过调试模式进行测试

This should be simple - test to see if a value is null, and if it's not, create a JS Date object from the .NET property, if it is, create a new JS Date object, but for some reason, it want's to evaluate and execute that line, even though HasValue is false.

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

Really stumped. Has anyone seen something like this?

真的难住了。有没有人见过这样的事情?

采纳答案by Tommy

I can see a couple of things going on here that are impacting your ability to render the correct data.

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

First, the MVC variables are processed on the server side. Your current implementation is always trying to render a value for the @Model.Birthday.Valueproperties in your Javascript in order to generate the HTML. This will happen regardless if the property is true or false in your current example since it is relying on the client-side Javascript to do the conditional and not Razor. Below is a complete working example of your issue.

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

View Model

查看模型

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

        public DateTime? DateWithValue { get; set; }
    }
}

Controller

控制器

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

View

看法

@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>

Now obviously, the code is duplicated in the Javascript section in order to show it works for both Null and Non-null values in the same controller action.

现在很明显,在 Javascript 部分复制了代码,以显示它对同一控制器操作中的 Null 和非空值都有效。

As you can see in the View, we are ensuring that we are using the Razor syntax for the checking of the Model and Javascript for setting the actual client-side variable. Also, I wonder if your '- 1' was working properly. In order to do the subtraction in this example, I had to cast that value to an Int from the Javascript, but this is a minor detail.

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

For reference, this is an MVC 4 project on VS2012, Windows 8 Professional tested with Chrome.

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

回答by Radim K?hler

Solution in a nutshell:

解决办法简而言之:

I tested your code and could say, there is no issue with your HW/SW update. I am running VS 2010 on Win 7. The solution could be Change your code for example this way

我测试了你的代码,可以说,你的硬件/软件更新没有问题。我在 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>


Detailed explanation:

详细解释:

to find the answer let split what is the snippet above doing. It is justrendering an HTML code. Let's see it step by step

为了找到答案,让我们拆分上面的代码片段在做什么。它只是呈现 HTML 代码。让我们一步一步来看看

I. HasValue

一、拥有价值

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

@Model.Birthday = 新日期(2012,11,4)

1) Razor is sending to Response stream string until the first @operator

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

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

if("

2) here Razor evaluates this part @Model.Birthday.HasValue as a boolean and converts it to string so the next part of a code would be

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

True

3) Append next direct string

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

"){
    var today = new Date("

4) evaluat the @Model.Birthday.Value.Year and inject its string value

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

2012

5) 6) 7) ... and so on the final result sent to Response is:

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>

II. Birthdate is NULL

二、出生日期为 NULL

In case that the @Model.Birthday = nullthe first steps 1), 2) and 3) are the same:

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

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

    if ("True"){
        var today = new Date("

4) Exception Nullable object must have a value

4) Exception Nullable 对象必须有值

Finally, there is a place where we get the Nullable exception.

最后,有一个地方我们会得到 Nullable 异常。

@Model.Birthday.Value.Year

@Model.Birthday.Value.Year

is called while

被称为同时

@Model.Birthday == null

@Model.Birthday == null

回答by CupawnTae

The problem is that you're mixing up client-side code and server-side code. The javascript is run client-side, but only after all the server-side code has been completed.

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

So @Model.Birthday.HasValue, @Model.Birthday.Value.Year etc. will all be evaluated on the server-side, before it ever gets anywhere near the browser. The javascript code (and therefore in this case, the if statement) will never get to the browser as the exception is occurring server-side, trying to evaluate Model.Birthday.Value.Year on a null object.

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

You need to move the conditional server-side, e.g.

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

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

回答by Rikin Patel

Multi-line Code

多行代码

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

Single-line code

单行代码

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