Encode HTML, JavaScript, and URL Query Strings In ASP.NET Core
When a web page accepts an input from the end user it can also include
malicious data consisting of special characters, HTML tags, JavaScript code and
the things like that. As a safety measure you should encode such data before
displaying it back on to a page or while passing through URL query strings. To
that end ASP.NET Core providers three encoder classes that help you accomplish
just that. This article discuses how these classes can be used to encode HTML
markup, JavaScript code and URL query strings.
Consider the following simple ASP.NET Core MVC view:

The view consists of a textarea and a button. Now user can enter any kind of
values in the textarea - plain text, HTML markup, JavaScript code or even
certain special characters.
Suppose the data entered in the textarea is to be displayed back onto some
other page. Or the data is to be passed to another page through query string. As
you might have guessed if this data is used as it is (without encoding) it can
pose a security risk to the website. And therefore you should always encode it
before sending it to any page.
Moreover, your choice of encoding depends on the intended use. For
example, if the data is being passed through a query string then you should URL
encode it. If the data is being displayed as a part of HTML fragment then you
should HTML encode it. And if the data is being used in JavaScript then it must
be JavaScript encoded.
Luckily, ASP.NET Core provides a quick way to deal with the situation. You
can inject HtmlEncoder, UrlEncoder, and JavaScriptEncoder objects into your
controller and then encode the end user input using the required encoder. These
classes come from System.Text.Encodings.Web namespace.
Let's
see how this can be done:
public class HomeController : Controller
{
HtmlEncoder htmlEncoder;
UrlEncoder urlEncoder;
JavaScriptEncoder jsEncoder;
public HomeController(HtmlEncoder html,
UrlEncoder url,
JavaScriptEncoder js)
{
this.htmlEncoder = html;
this.urlEncoder = url;
this.jsEncoder = js;
}
}
As you can see, the HtmlEncoder, UrlEncoder and JavaScriptEncoder objects
have been injected into the controller and are stored in the local variables for
later use.
The following markup goes inside the Index view:
<form asp-action="Process" asp-controller="Home"
method="post">
<label for="textArea1">Enter some text :</label>
<br />
<textarea name="textArea1" rows="4" cols="40">
@ViewBag.UnencodedData
</textarea>
<br />
<input type="submit" name="submit" value="Encode" />
<br /><br />
<div>@Html.Raw(@ViewBag.EncodedData)</div>
</form>
The form tag helper sets the asp-action and asp-controller attributes to
Process and Home respectively indicating that the form will be handled by the
Process() action of the HomeController.
You will store the un-encoded value in ViewBag.UnencodedData property and the
encoded value in the ViewBag.EncodedData property. This way we can display both
for our testing purpose. The un-encoded value is outputted in the textarea.
Assuming that we have HTML encoded the data the <div> element outputs the HTML
encoded value. Why did we use Html.Raw() in the code? That's because the Razor
engine automatically HTML encodes whatever you output using @ syntax. Here, we
want to see whatever has been passed from the controller without any HTML
encoding. And hence we used Html.Raw().
Now add the Process() action to the HomeController and write the following
code into it:
public IActionResult Process(string textArea1)
{
ViewBag.UnencodedData = textArea1;
ViewBag.EncodedData = htmlEncoder.Encode(textArea1);
return View("Index");
}
The code retrieves the value entered in the textarea through model binding
(textArea1 parameter). It stores the un-encoded value in the UnencodedData
property of ViewBag. It then uses the HtmlEncoder object and encodes the value
using its Encode() method. The HTML encoded value is stored in the EncodedData
property of the ViewBag.
To test how the HTML encoder works, run the application and enter <h1>Hello
World!</h1> into the textarea. Upon clicking the Encode button you should see
this result:

As you can see, the textarea displays the original HTML markup whereas the
<div> element displays its HTML encoded equivalent.
Now let's use the UrlEncoded object. Modify the Process() method as shown
below:
public IActionResult Process(string textArea1)
{
ViewBag.UnencodedData = textArea1;
ViewBag.EncodedData = urlEncoder.Encode(textArea1);
return View("Index");
}
The code is quite similar to the previous example. But this time we used
UrlEncoder object's Encode() method to URL encode the data.
You also need to tweak the Index view as shown below:
<form asp-action="Process"
asp-controller="Home" method="post">
<label for="textArea1">Enter some text :</label>
<br />
<textarea name="textArea1" rows="4" cols="40">
@ViewBag.UnencodedData
</textarea>
<br />
<input type="submit" name="submit" value="Encode" />
<br /><br />
<a href="/home/showdetails?data=@Html.Raw(@ViewBag.EncodedData)">
Click here to know more!
</a>
</form>
This time we display the EncodedData as a part of a URL query string. Upon
running the application (enter <h1>"Hello" 'World!'</h1> for testing) if you see
the page source, you will see something like this:

Now the value properly URL encoded and is safe to pass in query string.
Finally, let's see JavaScriptEncoder in action. Modify the Process() action
as shown below:
public IActionResult Process(string textArea1)
{
ViewBag.UnencodedData = textArea1;
ViewBag.EncodedData = jsEncoder.Encode(textArea1);
return View("Index");
}
This time we use the JavaScriptEncoder object's Encode() method.
Also modify the Index view as shown below:
<form asp-action="Process"
asp-controller="Home" method="post">
<label for="textArea1">Enter some text :</label>
<br />
<textarea name="textArea1" rows="4" cols="40">
@ViewBag.UnencodedData
</textarea>
<br />
<input type="submit" name="submit" value="Encode" />
<br /><br />
<script>
document.write('@Html.Raw(@ViewBag.EncodedData)')
</script>
</form>
This time we outputted the EncodedData in a <script> block using
document.write() method.
The following figure shows a sample run of the application:

The page's source will reveal how the JavaScript encoded value is being used:

To know how these encoders can be used to prevent cross-site scripting
attacks go
here.
That's it for now! Keep coding!!