Passing .NET Server-Side Data to JavaScript

There are a lot of different ways to pass C# data from an ASP.NET back end to a JavaScript front end. In this post, I want to highlight a variety of methods and point out their pros and cons. In particular, I'll focus on how to embed data within the HTML document that's being loaded.

Passing Data from C# to JavaScript

Method #1: Fetching Data by Making an AJAX Request

I would argue that this is the classic: After an HTML page has finished loading, an AJAX request is made to fetch some data from an endpoint provided by the back end. Borrowing from Pirates of the Caribbean, this could look something along the lines of the following:

var pirates = [];

// Assuming you have referenced jQuery
$(function() {
    $.getJSON("/black-pearl/crew", function(crewResponse) {
        pirates = crewResponse.pirates;
    });
});
  • Pros: Making an AJAX request is a well-known, easy-to-implement solution to pass data from ASP.NET to JavaScript. With technologies such as ASP.NET Web API, pretty much all of the plumbing work like content negotiation and serialization is done for you.
  • Cons: An additional HTTP request takes time to complete, which means the requested data isn't available immediately after page load. You'll also have to adapt your code to work with data coming in asynchronously.

Method #2: Loading Data Through an External JavaScript File

Instead of directly fetching the desired data from an endpoint through an AJAX request, you can also put the data in an external JavaScript file and reference it in a <script> tag. You can even embed Razor code withing that script file while still getting first-class tooling from Visual Studio, as shown in my blog post Generating External JavaScript Files Using Partial Razor Views. You'd then simply reference the script file like this:

<script src="/black-pearl.js"></script>

Using an external JavaScript file is very similar to making an AJAX request and pretty much has the same pros and cons. However, working with a classical AJAX request is probably a little nicer because you can very easily register a callback to be executed once the response arrives; doing the same with external JavaScript files might be more cumbersome. For the sake of completeness, this method is included in this overview, though.

Method #3: Opening a Persistent Connection with SignalR

You can also choose to open a persistent connection to your server with SignalR. This is a great method for any type of application which benefits from real-time data, like chat programs or client/server games.

Under the hood, SignalR tries to establish the connection using Web Sockets if both the server and the client support them. If not, it gracefully falls back to mechanisms like server events, forever frames, long polling, etc. and thereby ensures wide browser (and server) support. I encourage you to check out Damian Edwards' and David Fowler's talk Building Real-time Web Apps with ASP.NET SignalR for an introduction to SignalR.

Method #4: Attaching Data to HTML Elements

If you have primitive data that's closely related to an HTML element, it might be best to attach that data to the element using HTML 5 data- attributes:

<ul>
    @foreach (var pirate in pirates)
    {
        <li id="@pirate.FirstName" data-rank="@pirate.Rank">@pirate.FullName</li>
    }
</ul>

Let's assume the following output:

<ul>
    <li id="jack" data-rank="captain">Jack Sparrow</li>
    <!-- The rest of the crew is omitted for brevity. Sorry. -->
</ul>

Finding out Jack Sparrow's rank is now as simple as that, again using jQuery:

var jacksRank = $("#jack").data("rank"); // "captain"

While this method of rendering inline-data is great for simple data, it doesn't work well for anything beyond primitive types. This is where #5 will come in handy in just a moment.

Method #5: Assigning Data Directly to a JavaScript Variable

Coming back to primitive values once more, there's also the possibility to assign data to a JavaScript variable, just like this:

var blackPearlHomePort = "@Url.Content("~/tortuga")";

For simple values like the above one, this is my favorite approach since it neither requires loading an external resource (thus resulting in an additional HTTP request) nor pollutes any HTML elements.

Method #6: Serializing a .NET Object into a JavaScript Literal

Finally, let me show you the approach I like to use when dealing with complex objects. It uses a custom Json.NET serializer to turn .NET objects into their JavaScript literal representation.

Let's assume we have defined the following ASP.NET MVC action …

public ActionResult Index()
{
    var pirates = new List<Person>
    {
        new Person("Jack", "Sparrow"),
        new Person("Will", "Turner"),
        new Person("Elizabeth", "Swann")
    };

    return View(new BlackPearlViewModel(pirates));
}

… and view model:

public class BlackPearlViewModel
{
    public IEnumerable<Person> Pirates { get; private set; }

    public BlackPearlViewModel(IEnumerable<Person> pirates)
    {
        Pirates = pirates;
    }
}

Let's also create a JavaScriptConvert class that will serialize arbitrary .NET objects:

public static class JavaScriptConvert
{
    public static IHtmlString SerializeObject(object value)
    {
        using (var stringWriter = new StringWriter())
        using (var jsonWriter = new JsonTextWriter(stringWriter))
        {
            var serializer = new JsonSerializer
            {
                // Let's use camelCasing as is common practice in JavaScript
                ContractResolver = new CamelCasePropertyNamesContractResolver()
            };

            // We don't want quotes around object names
            jsonWriter.QuoteName = false;
            serializer.Serialize(jsonWriter, value);

            return new HtmlString(stringWriter.ToString());
        }
    }
}

JavaScriptConvert almost works like Json.NET's native JsonConvert serializer, except that it removes quotes around object names and enforces camelCased property names. The cool thing is that the CamelCasePropertyNamesContractResolver is being smart about abbreviations like "ID", which will not be turned into "iD", but into the all-lower "id".

In the corresponding Razor view, we can now use our custom serializer as follows:

<script>
    var pirates = @JavaScriptConvert.SerializeObject(Model.Pirates);
</script>

For the pirates defined in our above action method, the output will be this:

<script>
    var pirates = [{firstName:"Jack",lastName:"Sparrow"},{firstName:"Will",lastName:"Turner"},{firstName:"Elizabeth",lastName:"Swann"}];
</script>

Note that we can configure the serializer to prettify the output by setting its Formatting property to Formatting.Indented, which will insert appropriate line breaks and spaces to make the output more readable. Also note that the output is not valid JSON because the property names aren't wrapped in quotes.

Conclusion

You have a variety of options how you can move data from your .NET back end to a JavaScript client. Depending on your requirements, you can choose to either load the data by making an additional HTTP request (#1 and #2), connect to your server using SignalR (#3), or embed the data within the document that's being requested (#4, #5, and #6). The big advantage of #4, #5, and #6 is that the JavaScript data is inlined within the HTML document, so you won't have to wait for it to load. As long as you don't put megabytes of data in there, you should be fine.

Hope this helps,

Marius

P.S: Also make sure to check out my favorite tech-related books!

Related Articles:

Thanks to Stewart and Julien who pointed out in their comments to include SignalR in this list.

Use the coupon code LAUNCHDAY for $10 off!

Learn ES6

30 Comments

Stewart Beck

You forgot the excellent new member of the family SignalR.

Anton

I use something like this in Views:

<script type="text/javascript">
    var model = @Html.Raw(Json.Encode(Model));
    // your js code here
</script>

An then all Model data is available in JS same as on C#. No camel casing like this, but then when i see JS object with Capital letter, i know it's from Model.

Julien C

In my current pet project I'm using SignalR to move data too and from the server, with the added bonus of being able to synchronize multiple simultaneous sessions. Loving the flexibility

Marius Schulz

Stewart & Julien: Thanks for pointing out that I didn't list SignalR as a separate method. I've updated the post accordingly.

Francesco

CamelCasePropertyNamesContractResolver is very dangerous, and may lead to bugs for two reasons:

  1. Conversion rules are non a strong standard (as you noticed ID is converted into id) so some developers may introduce bugs because of a uncertainties on the names that are created.
  2. As your post point out the same application may exchange data with the server in several ways...so we must be sure that camel convention enforcement is performed by all these methods ...and in the same way to ensure coherence....moreover some third parties libraries may not use the camel enforcement...simply because it is not a standard...so the only way to avoid compatibility and coherence problems...is avoiding the use of the CamelCasePropertyNamesContractResolver....and convincing all other people to do the same :)
GuyO

Thank you for this great article. What are the possibilities to pass data the other way from JavaScript (web page) to .NET Server-Side ?

Daniel Mackay

In method # 5, what is ~/tortuga? Is it a file, or a service?

Marius Schulz

GuyO: Excellent question! On top of my head, I can come up with these ways:

  • making an AJAX request (with an appropriate HTTP method)
  • submitting a form (with input fields populated by JavaScript)
  • writing the data into a cookie (automatically sent with each request)
  • using the SignalR connection (or Web Sockets, for that matter)
  • requesting a resource (e.g. <img src="..." /> (with data in the URL)
Marius Schulz

Daniel: It can be anything, really, it doesn't matter, but let's say it's an API endpoint. I just wanted to illustrate how to construct URLs on the server side and then pass them to the JavaScript client.

I do this pretty often to get my application's root URL:

var appRootUrl = "@Url.Content("~/")";

Take my blog, for example, which is an ASP.NET MVC application: locally, it's hosted under localhost/blog; therefore, the appRootUrl contains the value /blog/. In production, my blog is hosted unter blog.mariusschulz.com, so appRootUrl is set to / (just a single slash) now.

If I did something like this, …

$.get("/blog/recent-comments", function() {
    /* ... */
});

…, it would work just fine offline (as long as the application runs under /blog), but not online because blog.mariusschulz.com/blog would be the wrong URL. So I do it this way instead:

$.get(appRootUrl + "recent-comments", function() {
    /* ... */
});
Adam Jasper

The main drawback to methods 5 and 6 is that they require the Razor view engine. Therefore, you cannot make your Javascript unobtrusive by putting it in an external file i.e. black-pearl.js.

Marius Schulz

Adam: You're right, Razor code won't be executed in plain .js files, which is why I wrote the post Generating External JavaScript Files Using Partial Razor Views. Make sure to check it out!

Yves

There's one more solution which I'm currently looking for: Assigning JavaScript code verbatim to ASP.NET controls like <script runat="server" id="...">. I've done it before but don't remember how it worked anymore. Right now the control variable is always null which actually cannot be.

Tosin

Hello, Thanks for this resource. I am assuming tortuga is the name of the current cshtml file in method 5. I am still confused on how exactly to get access in javascript to the data that i want from that example (say Jack's rank). Thanks

MAS

Thank you Marius Schulz, this helped me a lot.

Chris

For 4,5,6... Im just wondering what people think about rendering the json in a script tag, ex:

<script id="MyViewModelAsJson" type="application/json"> json goes here </script>.

One can argue that it doesn't pollute the global namespace.

Also, what about using an action that return a JsonResult (or any custom json.net result) and calling this action in the razor view?

Marius Schulz

Chris: Interesting approach, the JSON <script> tag!

Outputting the returned JSON of an action in a view is basically the same as #5 because you're inlining the data into the rendered HTML.

Aryan Raj

Great going, it's an excellent article for a beginner as well.

Scott M.

Great Job! Thanks

BRam

Very nice article !

I am a novice in web programming and for one of my projects, I was using very primitive method. Having a hidden html element that is bound to a model. The Javascript code retrieves the value from the element.

i now have much better way of dealing with this.

Thank you.

dance2die

May I suggest to add "ViewBag" to the list?

Nuredin

Nice post,

I have one question,

What would be the best option to avail list of users on auto complete text box from exchange web service?

m.nezafat

That's Perfect I surf on Internet to find the best ways sending local data with model to my server side! Can U help me. I ass model to my View I Use Datatable Grid(www.datatables.net) in my View and add or edit some record with ajax for that grid at last when i press submit i want to get model data & data of grid that i change(add,delete,update) i cant find ways for this question thank if you can help me

m.nezafat

I forgot to say that I programming with asp.net mvc and I should do it in razor view

Darrell

Great blog posts!

I am looking to find a way to achieve this for my scenario. I am using TypeScript in my MVC 6 project. My Razor views purely contain the HTML markup, and then a script include to the external javascript file, which is generated via typescript. Therefore I can not use the technique from your previous blog post for the external js file, because the razor view engine does not support typescript. And typescript does not have Razor like capabilities - i.e it knows nothing about the current request. I am trying to think if there is something clever I can do to solve this problem but it's looking like the only current solution (without resorting to AJAX) is going to be to define some common javascript API, where my MVC razor page can "register" some data with a javascript call, and then later my external js that needs the data, can "request" that data, and its all mediated by some client side object. This is going to be a little bit more involved though so I was hoping there might be some other trick I could do to leverage MVC more..

Zev

Thank you so much for a very useful article

xtex

Assume the endpoint is the Worldbank for instance, or any open data, where you can get data as JSON, and assume you want to send them as JSON to the client (e.g. to display them on google charts). What I did sofar was method #1, i.e. my website delivers the html+js and the client will invoke AJAX to retrieve the json and use google charts to display this json. I am wondering if I cannot get the data on the server and deliver it to the user, but without transforming the json into poco's and back to json.

Abdul Hameed

Excellent article

Mengchao

Excellent article! Thank you very much for sharing this.

Michael McGowan

I used Method #6 and it works great! Thank you so much!

Fredy Guibert

Thanks bro! Your post helped me a lot! More ideas, code more efficient! Regards and keep posting! @fredyfx