3 using System.Collections.Generic;
4 using Nancy;
5
6 public class ShortUrlModule : NancyModule
7 {
8 private static readonly Dictionary<string, string> urlMap = new Dictionary<string, string>();
9
10 public ShortUrlModule()
11 {
12 Get["/"] = _ => View["index.html"];
13 Post["/"] = _ => ShortenUrl();
14 }
15
16 private string ShortenUrl()
17 {
18 string longUrl = Request.Form.url;
19 var shortUrl = ShortenUrl(longUrl);
20 urlMap[shortUrl] = longUrl;
21
22 return ShortenedUrlView(shortUrl);
23 }
24
25 private string ShortenUrl(string longUrl)
26 {
27 return "a" + longUrl.GetHashCode();
28 }
29
30 private string ShortenedUrlView(string shortUrl)
31 {
32 return string.Format("<a id=\"shorturl\" href=\"http://{0}/{1}\">;http://{0}/{1}</a>", Request.Headers.Host, shortUrl);
33 }
34 }
Specifically the last method, 'ShortenedUrlView' is bad code: It's brittle, it doesn't produce valid HTML, and it's open for script injection. Therefore I want to separate that bit of view code from the module code: I want a view engine. Luckily Nancy supports a number of standard view engines(Razor, Spark, DotLiquid, NDjango) each of which are only a NuGet package away, but it also comes with its own appropriately named Super Simple View Engine, SSVE. For this sample SSVE will do, so let's just stick with that.
We add a file called shortened_url.sshtml to the Views folder and put this into it:
<html>
<body>
<a id="shorturl" href="http://@Model.Host/@Model.ShortUrl">
http://@Model.Host/@Model.ShortUrl
</a>
</body>
</html>
As with Razor views the @ indicates code snippets. In the above we insert 'Host' and 'ShortUrl' properties from the view model in the view.
To use this we also need to modify the Nancy module code a bit. We need to return a View[] instead of simply a string:
21 private Response ShortenUrl()
22 {
23 string longUrl = Request.Form.url;
24 var shortUrl = ShortenUrl(longUrl);
25 urlMap[shortUrl] = longUrl;
26
27 return View["shortened_url",
28 new { Host = Request.Headers.Host, ShortUrl = shortUrl }];
29 }
30
31 private string ShortenUrl(string longUrl)
32 {
33 return "a" + longUrl.GetHashCode();
34 }
35
We saw use of View[] last time, this time around we provide a model object along with the view name. This object is passed to the view code as the @Model.
That's it. Introduced a view engine. No friction.
The code for this sample is still available on GitHub. Now with the updates described here.
No comments:
Post a Comment