0
votes

I am making ajax call to server requesting some data. for eg: http/get(SomeDataService). In controller i have data object as below:

API Controller:

public DataCollection getSomeData()
{
try{
// get the data in object and checking its null or not. 
//If not null, will bind the data in ko viewModel.if null throw below exception.
}
catch(Exception e)
{
e. message(" No Data Found")
}
}

Now i want to bind the "No data found" message inside KO viewModel and view.

Please suggest me how to do this? I am new to KO, ASP.net

I am re-posting again what i need actually. 1. Making web api Ajax call

function GetData() {

            var data = http.get(apiUrl)
            .success(function (data) {
                if (data != null )
                {
                    // some stuff for success data

                    vm.getDataSuccess;
                }
                else {
                    vm.errorMessage();// server side exception message.

            })
  1. WebApi controller:

    public DataCollection GetSomeData() { var data = GetData(); if( data == null ){ throw new Exception("Data is null");

    }

  2. I have created viewmodel like below:

    var vm = { activate: activate, getDataSuccess: ko.observableArray(), errorMessage:ko.observable(), title: 'TopNews' };

  3. bind on view page in one of the div

    -- <-div class="error" data-bind="text: errorMessage" />

    i am not sure above method is correct or not. but i need like this.

4

4 Answers

1
votes

On your server side code, you should wrap the exception into an HttpResponseException:

try
{
    // ... your stuff here
}
catch (Exception exception)
{
    throw new HttpResponseException(new HttpResponseMessage(HttpStatusCode.InternalServerError)
    {
        ReasonPhrase = exception.Message
    });
}

You can catch this message generally on the .ajaxError handler of jquery.

Or even fancier, create a custom KO binding:

ko.bindingHandlers.flash = {
    prepareInfo: function (valueAccessor) {
        var info = {},
            options = ko.utils.unwrapObservable(valueAccessor());

        if (options && options.value) {
            info.value = options.value;
        } else {
            info.value = valueAccessor();
        }

        return info;
    },
    init: function (element, valueAccessor) {
        var info = ko.bindingHandlers.flash.prepareInfo(valueAccessor);

        $(element)
            .ajaxError(function (event, xhr, ajaxSettings, errorThrown) {
                info.value(errorThrown);
             }).ajaxSend(function () {
                info.value(null);
             });

        $(element).hide();
    },
    update: function (element, valueAccessor) {
        var info = ko.bindingHandlers.flash.prepareInfo(valueAccessor);
        if (info.value()) {
            $(element).stop().hide().text(info.value()).fadeIn(function () {
                clearTimeout($(element).data("timeout"));
                $(element).data("timeout", setTimeout(function () {
                    $(element).fadeOut('fast');
                    info.value(null);
                }, 3000));
            });
        }
    }
};

And then just add a DIV somewhere in your HTML with a data-bind to this binding.

0
votes

you have to add it to the model youre returning to the view ie. your viewmodel.

if youre using ajax, then the exception you throw will be returned to the ajax function call:

$.ajax({
            type: "POST",
            url: "/chart/setfilter",
            data: JSON.stringify(filters),
            dataType: "json",
            contentType: "application/json; charset=utf-8"
        }).done(function (res, status, xhr) {
            //here res will contain the exception

        });
0
votes

You sould use the success and error parameters (doc).

Try something like this.

$.ajax({
    type: "GET",
    url: "error.com", // your url
    error: function (jqXHR, textStatus, errorThrown) {
        vm.response('Error ' + errorThrown)
    },
    success: function (respo) {
        vm.response("Success" + response)
    }
})
0
votes

In my experience, the best way to handle this seamlessly is to set up your web api so that it is not responsible for handling unanticipated errors. This keeps the web api code very clean and simple, like this:

public DataCollection GetSomeData()
{
    var data = GetData();
    return data;
}

If you'd like to throw a custom exception for whatever reason - maybe you have a specific message to display if the data is null - you can throw the exception normally:

public DataCollection GetSomeData()
{
    var data = GetData();
    if( data == null ){
        throw new Exception("Data is null");
        //or... throw new MyCustomException("Data is null");  
    }
}

Now, so far this approach is not acceptable, because it can potentially expose sensitive server information to the client. In order to handle this cleanly, create a custom action filter that handles the exceptions. Something like this:

/// <summary>
/// Represents an attribute that will automatically process any unhandled exceptions
/// that occur during during the execution of a web api action
/// </summary>
public class HandleExceptionAttribute : ExceptionFilterAttribute
{
    public override void OnException(HttpActionExecutedContext actionExecutedContext)
    {
        //log the error (make sure LogError doesn't throw any exceptions)
        LogError(actionExecutedContext);

        //set up a default message that is safe to send to the client 
        // (doesn't expose any sensitive exception information)
        var message = "An error has occured please try your request again later";

        //if the exception is, or inherits from MyCustomException, then 
        //  go ahead and forward the message on the client
        if (actionExecutedContext.Exception is MyCustomException)
        {
            message = actionExecutedContext.Exception.Message;
        }

        actionExecutedContext.Response = 
            actionExecutedContext.Request.CreateResponse(HttpStatusCode.InternalServerError, message);
    }
}

Be sure to apply this action filter globally, so that it applies to all web api methods without any developer intervention. That way you can be confident that no unhandled exceptions are throwing raw exception messages back to the client.


Now that you have the error coming back from the server properly, you can display the message to your users in a number of ways. The cleanest thing to do is to simply display the message immediately and not try to add it to the view model. You can display a message to the user using toast.js or some other notification mechanism (even window.alert() until you get further down the road).

Here's another question on Stack Overflow that may help with this decision: knockout js best practices ajax error handling