简体   繁体   中英

How to set Entity Framework data to JavaScript variables?

I have a website that uses ASP.NET MVC, and I store my data using Entity Framework.

Here is what one of my Razor View Pages looks like:

@model IEnumerable<GPBuddy.DataContexts.Item.History>

@{
    String arr = "";
    foreach (var item in Model)
    {
        arr += item.current_price_raw.ToString() + ",";
    }
    arr = arr.TrimEnd(',');
}

<div id="testData">

</div>

<script type="text/javascript">
    var array = '@arr';
    var prices = array.split(",");
    text = "<ul>"
    for (i = 0; i < prices.length; i++) {
        text += "<li>" + prices[i] + "</li>";
    }
    text += "</ul>";
    document.getElementById("test").innerHTML = text;
</script>

UPDATED: We are now able to set JavaScript variables to EF variable data.

Here is what the html looks like:

<div id="testData">

</div>

<script type="text/javascript">
    var array = '2051,2034,1908,1908,1887,1887,1680,1610,1549,1452,1411,1421,1439,1464,1533,1608,1763,1958,2027,2070,2077,2043,2026,2026,2013';
    var prices = array.split(",");
    text = "<ul>"
    for (i = 0; i < prices.length; i++) {
        text += "<li>" + prices[i] + "</li>";
    }
    text += "</ul>";
    document.getElementById("test").innerHTML = text;
</script>

You'll want this:

var array = [ @( String.Join( ", ", this.Model.Select( i => i.current_price_raw ) ) ];

Your original code has problems, which my single-line solution above avoids:

  • Concatenating System.String in a loop is bad for performance (with geometric runtime complexity because each string concatenation (of n and m characters in length) and allocates n+m on every iteration.
    • Use String.Join to create a comma-separated list, this also avoids needing to Trim any trailing comma ( Trim also creates a new string allocation too).
  • Your JavaScript code was rendered without the JavaScript literal-array syntax ( [x,y,z] ), your original rendered code was just declaring a series of literal integer expressions.
  • You can use Linq to make code more succinct with zero (or negligible) performance impact (in my case, using Select instead of foreach ).

I will say that writing JavaScript and JSON in Razor is difficult because they both use curley-braces as delimiters, this was a lot easier with ASPX <%= delimiters.

Update:

Your code to extract individual elements is inefficient because you're splitting a string and doing string-to-int conversion, that's useless. Your code will be significantly faster (and easier to read) if you use native JavaScript arrays like in my original example. You should also use the DOM API instead of generating HTML in text. Here is my version of your follow-on code:

var array = [ @(String.Join( ",", this.Model.Select( i => i.current_price_raw ) ) ) ];

var ul = document.createElement("ul");

for (i = 0; i < array.length; i++) {
    var li = document.createElement("li");
    li.textContent = array[i].toString();

    ul.appendChild( li );
}

document.getElementById("testData").appendChild( ul );
  • string.split is an expensive operation
  • JavaScript string concatenation can also be expensive. Different JS runtimes (V8 vs Chakra etc) implement strings differently and "cheap concatenation" is never guaranteed. I am annoyed JavaScript does not have a StringBuilder equivalent.
  • Forming HTML using string concatenation is inherently dangerous the same way generating SQL with concatenation is: if you have any user-input which is not properly sanitized (or even if it is sanitized) you run the risk of XSS and other code-injection attacks.
  • Another reason to avoid HTML-as-strings and using innerHTML is that it invokes the browser's HTML parser, which is not cheap. By using the DOM API directly ( document.createElement , element.appendChild , etc) you avoid the parser completely and so maximize performance. Use innerHTML only when appropriate (such as when using the DOM API might be unwieldy).

Update 2:

As the first commentator points out, if you're not going to be using your data in another script it's faster to render it directly in Razor:

<ul>
@foreach(var item in this.Model) {
    <li>@( item.current_price_raw )</li>   
}
</ul>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM