Blog

A gotcha I found with Font Awesome's CDN


Something I was running into when I was programming something involving dynamic classes in the DOM using AngularJS's ngClass... The Font Awesome icon wasn't loading.

It was quite strange, as if I had the class declared on page load, it would show the icon.

As I delved deeper into this, and looked at the active page source in Chrome's developer tools, I noticed that instead of the DOM element with a class name, I was seeing SVG.

Well, guess what: In my efforts to asynchronize a few things, I had used the SVG & JS method of using their deferred script tag:

<script defer src="https://use.fontawesome.com/releases/v5.2.0/js/all.js" integrity="sha384-4oV5EgaV02iISL2ban6c/RmotsABqE4yZxZLcYMAdG7FAPsyHYAPpywE9PJo+Khy" crossorigin="anonymous"></script>

As you can see, this was not the best decision for my use-case.

Gotta use the Web Fonts/CSS method:

<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.2.0/css/all.css" integrity="sha384-hWVjflwFxL6sNzntih27bfxkr27PmbbK/iSvJ+a4+0owXq79v+lsFkW54bOGbiDQ" crossorigin="anonymous">

Note that 5.2.0 was their current version. Your mileage may vary.

So yeah, if you're going to do dynamic class adding or deletion to anything in your web project, and you want to use their CDN, best use the CSS version. Otherwise, you could wind up spending upwards of three hours wondering why the icon's not showing up and thinking AngularJS isn't rendering the class change or something.

(It was late and I was tired. Shuddup).

Creating iCal files in ASP.NET MVC and C#


Recently, during a project I was working on for a client, I was tasked with adding events to a user's iCal in addition to being able to add events to Google Calendar. In researching this, I found that this would necessitate creating a .ics file for each event. Given that my client's site had hundreds if not thousands of events, that would be a lot of .ics files sitting around. There had to be a solution to this.

Fortunately, there is, and ASP.NET MVC and C# makes this surprisingly painless.

First, we need to know what goes into a iCal .ics file. This PasteBin page gives a very rough overview of a partial iCal format (the parts that I needed, as a bonus). It's at the bottom of the window, below the Google Calendar API and Yahoo Calendar API if you need those as well.

Now, while I had some of the spec, I needed a way to put it together into a .ics file. Now, there's some libraries out there, but I ran into this post at Balajiprasad's useful codes that had some sample code that I could adapt. He used a library for his solution. I opted for a simple Stringbuilder approach to start.


/// <summary>
/// Generates an iCalendar .ics link and returns it to the user.
/// </summary>
/// <param name="downloadFileName">Name of the download file to return.</param>
/// <param name="evt">The Event.</param>
/// <returns>The .ics file.</returns>
[System.Web.Mvc.HttpPost]
public ActionResult AddToICalendar(string downloadFileName, int eventId)
{
    // replace db with however you call your Entity Framework or however you get your data.
    // In this example, we have an Events collection in our model.
    using (
        var db =
            new ExampleEntities(
                ConfigurationManager.ConnectionStrings[YourConnectionString].ConnectionString))
    {
        // Alternatively, you may use db.Events.Find(eventId) if this fits better.
        var demoEvent = db.Events.Single(getEvent => getEvent.ID == eventId);

        var icalStringbuilder = new StringBuilder();

        icalStringbuilder.AppendLine("BEGIN:VCALENDAR");
        icalStringbuilder.AppendLine("PRODID:-//MyTestProject//EN");
        icalStringbuilder.AppendLine("VERSION:2.0");

        icalStringbuilder.AppendLine("BEGIN:VEVENT");
        icalStringbuilder.AppendLine("SUMMARY;LANGUAGE=en-us:" + demoEvent.EventName);
        icalStringbuilder.AppendLine("CLASS:PUBLIC");
        icalStringbuilder.AppendLine(string.Format("CREATED:{0:yyyyMMddTHHmmssZ}", DateTime.UtcNow));
        icalStringbuilder.AppendLine("DESCRIPTION:" + demoEvent.Description);
        icalStringbuilder.AppendLine(string.Format("DTSTART:{0:yyyyMMddTHHmmssZ}", demoEvent.StartDateTime));
        icalStringbuilder.AppendLine(string.Format("DTEND:{0:yyyyMMddTHHmmssZ}", demoEvent.EndDateTime));
        icalStringbuilder.AppendLine("SEQUENCE:0");
        icalStringbuilder.AppendLine("UID:" + Guid.NewGuid());
        icalStringbuilder.AppendLine(
            string.Format(
                "LOCATION:{0}\\, {1}\\, {2}\\, {3} {4}",
                evt.LocationName,
                evt.Address,
                evt.City,
                evt.State,
                evt.ZipCode).Trim());
        icalStringbuilder.AppendLine("END:VEVENT");
        icalStringbuilder.AppendLine("END:VCALENDAR");

        var bytes = Encoding.UTF8.GetBytes(icalStringbuilder.ToString());

        return this.File(bytes, "text/calendar", downloadFileName);
    }
}

And then, within the .cshtml file in question, we call it like this:


@using (Html.BeginForm("AddToICalendar", "Home", new { downloadFileName = "thisEvent.ics", eventId = Model.TheEvent.ID }))
{
    <input type="submit" value="Add to iCal" class="ical-button" id="button" /><br />
}

This will generate a form and will, when clicked, call the AddToICalendar function. It will then retrieve the event data and populate the fields in the generated .ics file with the relevant data. As a bonus, should you have the actual location data, someone on an iPhone or iPad can actually call up the map and get directions to go to wherever the event is located. (Now, how to call something other than Apple Maps as a default for this, I've yet to figure out and would prefer Google Maps or, better yet in my case, Waze).

The new Guid for the UID line will assign a new ID to this event. Now, if you had an event that would be updated, and wanted someone to just click on the same link and update their calendar that way, I would wager that you would have a different way of setting the UID earlier on and keeping it the same for the same event. I haven't had the opportunity to test this yet, but that's my understanding based on my research.

As an additional bonus, you can even download the .ics file on a Windows system and if you have Outlook, you can import that as an event into that calendar. I haven't tested this with other calendar applications or even Google Calendar. So in the end, this proved to not just be for iCal.

Also, if you wanted to keep the start and end date/times to a local time, you could remove the Z part in the string.Format strings for each, which would relegate it to be local to the user's time. Still, it's much better to use UTC-based time for everything in my opinion when feasible. As far as the formatting string, the {0:yyyyMMddTHHmmssZ} part would map to 20150601T123000Z if given a date/time of June 1st, 2015 at 12:30 UTC. Eliminate the Z part, and it becomes June 1st, 2015 at 12:30PM local time.

You'll also notice the double-backslash in front of the commas. For some reason, iCal needs those commas to be escaped, and a single backslash just won't do the job using this method. I've tested this without doing that in the generated iCal file, and it didn't work very well. On my iPhone, it would only put the LocationName before the first comma into the Location field on the Event entry in my iCal. With the proper escaping, it puts the entire address. I haven't tested what happens if you have a comma in one of those fields, so if you run into any problems you could easily put a .Replace(",", "\\,") onto the appropriate lines. The DESCRIPTION line, however, did not have this problem and did not seem to require the escaped commas, so it may just be for the LOCATION line. Have no worries about importing this into Outlook, as the backslashes won't show in the Location line on those events, at least not on my local Outlook with Office 365.

In closing, this should be a help to anyone who needs a basic iCal file to share events and reminders. I imagine the process would be similar if you wanted to make Reminders for iPhone/iPads the same way, and there are other fields that are available to put in these files too. This documentation at kanzaki.com should also be useful, however I don't really know if this is up to date. It's worth a shot though if you want to experiment. Happy coding.

New Portfolio Entries


Over the past couple weeks I've managed to get a couple more portfolio pieces up.

For the sites portfolio, I've recently completed some maintenance over at MyGiraffe, where users can submit events, sporting goods and other gatherings in the Greater Seattle Area. There's quite a few events to choose from, and my updates should add to its utility. In addition to Google Calendar links for each event, there's now the ability to add to iCal as well (for users on iPhones, Macs, etc.). In fact, even Microsoft Outlook users can import the iCal files and add these events to their calendars too, which is a nice plus. I'll be posting soon about how to create an .ics file in MVC using C# (which can be easily adapted to VB.NET if needed).

Another portfolio entry involves Mike & Jean's Berry Farm. They needed a couple pages for an equipment auction they held, and I was tasked with putting up the temporary pages for this (which are offline now). I decided to also make a couple header images to have the pages match the layout of the rest of the site. I adapted these from the original source materials when the site was created a few years back, and was able to replicate an image mask to have the images look similar in feel to the other images on the site. (The original file was missing this mask, so I had to find a way to remake it). Those header images are in my graphics portfolio.

It was a pleasure working with both clients, and would gladly work with them again!

Graphics Portfolio Up


After a decent bit of work, I have uploaded a small sampling of a graphics portfolio to supplement my sites portfolio. I have also added a couple more sites to the sites portfolio to further flesh out previous work.

While I am capable of some graphical work, my primary focus remains in the field of web development, both front-end and back-end.

In a pinch, I can do Photoshop/Illustrator/Fireworks, and have touched InDesign a bit. Get me behind a Visual Studio setup though, and that's where I shine much brighter.

Sites Portfolio Semi-Up


As promised, I have reopened my portfolio portion of my page. The graphics portfolio portion is still under reconstruction, and the sites section still needs more sites added back to it, but it's there.

To view what I have so far, click the Portfolio link on the top of the page (or in the menu if you're on mobile).

Also I've added a pop-up carousel for when a site's screenshot is clicked on the Sites Portfolio. The graphics portfolio will also have this feature. It was a little interesting to get this working within a Bootstrap modal window and referencing a Knockout viewmodel, but I got it done.

Now I'm taking a much-needed break before tackling more of this as my brain's turning into clay at the moment. Also more projects and portfolio entries to come, so stay tuned.

Links

Archive