How To Use IActionResult Abstraction To Achieve Graceful Degradation

You might have heard the term graceful degradation, as you know this term is kind of broad, but most of the time it refers to the page usability and the fact that when you rely on some language that are not available everywhere, the page still will be usable, w3’s article Graceful degradation versus progressive enhancement define it as:

Graceful degradation Providing an alternative version of your functionality or making the user aware of shortcomings of a product as a safety measure to ensure that the product is usable. Progressive enhancement Starting with a baseline of usable functionality, then increasing the richness of the user experience step by step by testing for support for enhancements before applying them. You may think that these two approaches sound very similar, and that they should give you pretty much the same result, but there are differences to take note of, which we’ll look at below.

I know I’m not exactly accurate about which one I’m using here, but it’s the concept that’s important. In my particular case, I’m going to apply it when I use JavaScript. In the following section I’m going to build a simple submit form that if JavaScript was enabled, I use JavaScript and Ajax to submit the form, and if it wasn’t, I’m going to submit the form without JavaScript, and all of that is possible through the use of IActionResult in Asp.Net Core or ActionResult in Asp.Net MVC 5. Although my example here is simple, the same concept can be applied when we have a more complicated scenario. What IActionResult does for use here is that it allows us to return a JsonRsult, ViewResult, or any other supported result to it, and in this particular scenario we can return JsonResult if the JavaScript was enabled and plain ViewResult if JavaScript was turned off, so let’s get straight to code:

        [HttpPost]
        [ValidateAntiForgeryToken]
        public async Task Create(ContactViewModel contactViewModel, bool isJavascriptEnabled)
        {
            if (!ModelState.IsValid) return View(contactViewModel);

            if (isJavascriptEnabled)
            {
                var contact = Mapper.ContactViewModelToContact(contactViewModel);

                int addContactResult = await _uw.ContactRepository.AddNewContactAsync(contact);

                if (addContactResult > 0)
                {
                    return Json(new { Status = "Success" });
                }

                return Json(new { Status = "ProblematicSubmit" });
            }

            var contactWioutJavascript = Mapper.ContactViewModelToContact(contactViewModel);

            int addContactResultWioutJavascript = await _uw.ContactRepository.AddNewContactAsync(contactWioutJavascript);

            if (addContactResultWioutJavascript > 0)
            {
                return View("Success");
            }

            ViewData["CreateContactMessage"] = "NothingToSaveOrThereWasAProblem";

            return View("Create", contactViewModel);
        }

Here we take a bool value called isJavascriptEnabled in our controller’s action, and what happen as a result is that if JavaScript was enabled, from our JavaScript code which is an Ajax request that is bound to submit event, we set the isJavaScriptEnabled to true, and the program control flow inters the if(isJavascriptEnabled) part and we return a JsonResult and if not, the program flow skip this part and go to the rest of our controller’s action which then return a ViewResult and indicate to our user that insert was successful, here’s my JavaScript code:

$("#ContactForm").on("submit", function (e) {
    e.preventDefault();

    var $form = $(this);
 
    var formParametersArray = $form.serializeArray();
 
    formParametersArray.push({ name: 'isJavascriptEnabled', value: true });
 
    if ($form.valid()) {
 
        $.ajax({
            type: "POST",
            url: "/Contact/Create",
            data: formParametersArray,
            dataType: "json",
            success: function (response) {

                if (response.status === "Success") {
                    successfulCreateNotice();
                    setTimeout(function () { window.location.replace("/Home/Index"); }, 3000);
                }
 
                 
                if (response.status === "ProblematicSubmit") {
                    ProblematicCreateNotice();
                }
 
            },
            error: function (xhr, status, error) {
                console.log(xhr.responseText);
            }
        });
 
 
    }
 
});

The important part here is where we push a new object into formParametersArray, and set the isJavascriptEnabled to true. For Html part we don’t have anything special, it’s just a normal form:

<form asp-action="Create" id="ContactForm" class="contact-form" method="post">
                
</form>
Share...
 

Hamid Mosalla

Hi, I'm Hamid Mosalla, I'm a software developer, indie cinema fan and a classical music aficionado. Here I write about my experiences mostly related to web development and .Net.