2

I am creating a custom command and want to handle exceptions in a userfriendly way, i.e. display an errormessage.

This is the code for my command:

public class ImportCommand : Command
{
    private readonly ICommandArgFactory _commandArgFactory;

    public ImportCommand(ICommandArgFactory commandArgFactory)
    {
        if (commandArgFactory == null) throw new ArgumentNullException(nameof(commandArgFactory));
        _commandArgFactory = commandArgFactory;
    }

    public override void Execute(CommandContext context)
    {
        NameValueCollection parameters = _commandArgFactory.GetArgs(context);

        Sitecore.Context.ClientPage.Start(this, "Import", new ClientPipelineArgs(parameters));
    }

    private void Import(ClientPipelineArgs args)
    {
        if (args.IsPostBack)
        {
            if (args.Result == "no") return;

            ProgressBox.Execute("Import", "Import", DoImport, args);
            SheerResponse.Alert("Import done!");
        }
        else
        {
            SheerResponse.Confirm("Are you sure?");
            args.WaitForPostBack();
        }
    }

    private void DoImport(object[] parameters)
    {
        BaseJob job = Sitecore.Context.Job;

        try
        {
            ClientPipelineArgs args = parameters[0] as ClientPipelineArgs;

            job.Status.State = JobState.Running;
            ...code here...
            job.Status.AddMessage("Parsing some more...");
            job.Status.State = JobState.Finished;
        }
        catch (CustomException ex)
        {
            Log.Error(mcxmfe.Message, this);
            job.Status.State = JobState.Finished;
            Sitecore.Context.ClientPage.SendMessage(this, mcxmfe.Message);
        }
        catch (Exception ex)
        {
            Log.Error(ex.Message, this);
            job.Status.State = JobState.Finished;
        }
    }
}

However, when my CustomException gets thrown, the code that I was hoping would print an error message in a popup also throws an error:

Sitecore.Context.ClientPage.SendMessage(this, mcxmfe.Message);

I've tried using SheerResponse.Alert(...) but that gives a NullReferenceException with the following stacktrace:

   at Sitecore.Web.UI.Sheer.ClientPage..ctor(HttpContextBase httpContext)
   at Sitecore.Context.get_ClientPage()
   at Sitecore.Web.UI.Sheer.SheerResponse.Alert(String text, String[] arguments)
   at [CustomCode]

I've also tried using Sitecore.Context.ClientPage.ClientResponse(...) but that also gave me a NullReferenceException with the following stacktrace:

   at Sitecore.Web.UI.Sheer.ClientPage..ctor(HttpContextBase httpContext)
   at Sitecore.Context.get_ClientPage()
   at [CustomCode]

How do I show an alert, when the exception is thrown in a background task?

2
  • After your job is completed you're using SheerResponse.Alert. Why don't you use the same for exception message? Feb 28 '20 at 20:48
  • I've tried moving the try-catch to be around the ProgressBox.Execute() call, but it seems that when the exception is thrown in the background job, it is not caught "outside" of the DoImport method if that makes sense
    – Hos
    Feb 28 '20 at 20:57
2

In the background the ProgressBox.Execute() is running the given method as a job where you don't have SheerResponse or ClientResponse.

Try the following:

  • add job.Status.Failed = true; when you handling the exception
  • use ProgressBox.Execute("Import", "Import", "<icon>", DoImport, "Something went wrong...", args); instead of ProgressBox.Execute("Import", "Import", DoImport, args);

The changes above should render the "Something went wrong..." text instead of the exception. This solution only good enough for you if you can display the same message when an error occurs.

4
  • JobState.Failed is not a valid enum in Sitecore 9.2 as far as I can see? That might also explain why I dont get to see the "Something went wrong..." text? I still see the exception
    – Hos
    Mar 5 '20 at 14:33
  • @Hos sorry, my mistake. It should be job.Status.Failed = true Mar 5 '20 at 14:48
  • 1
    I never got the "Something went wrong..." message to be displayed, however your input led me down the right path. Thank you! I will post my working solution for completeness sake and I will ofcourse mark your answer as accepted.
    – Hos
    Mar 5 '20 at 18:36
  • @Hos cool! Then mark your answer as the correct answer :) To not mislead later visitors. Mar 5 '20 at 19:48
2

This answer from Tamas led me down the right path, so I will mark that answer as the solution.

It seems that if you use job.Status.Failed = true together with job.Status.LogError("exception message"), the exception message will actually be displayed in a popup. Let me demonstrate:

public class ImportCommand : Command
{
    private readonly ICommandArgFactory _commandArgFactory;

    public ImportCommand(
        ICommandArgFactory commandArgFactory
    {
        if (commandArgFactory == null) throw new ArgumentNullException(nameof(commandArgFactory));
        _commandArgFactory = commandArgFactory;
    }

    public override void Execute(CommandContext context)
    {
        NameValueCollection parameters = _commandArgFactory.GetArgs(context);

        Sitecore.Context.ClientPage.Start(this, "Import", new ClientPipelineArgs(parameters));
    }

    private void Import(ClientPipelineArgs args)
    {
        if (args.IsPostBack)
        {
            if (args.Result == "no") return;

            ProgressBox.Execute("Import", "Import", DoImport, args);
        }
        else
        {
            SheerResponse.Confirm("Are you sure?");
            args.WaitForPostBack();
        }
    }

    private void DoImport(object[] parameters)
    {
        BaseJob job = Sitecore.Context.Job;

        if (job == null) return;

        try
        {
            ClientPipelineArgs args = parameters[0] as ClientPipelineArgs;

            job.Status.State = JobState.Running;
            ...code here...
            job.Status.AddMessage("Parsing some more...");
            job.Status.State = JobState.Finished;
        }
        catch (CustomException customEx)
        {
            Log.Error(customEx.Message, this);
            job.Status.LogError(customEx.Message);
            job.Status.Failed = true;
        }
        catch (Exception ex)
        {
            Log.Error(ex.Message, this);
            job.Status.LogError(ex.Message);
            job.Status.Failed = true;
        }
    }
}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.