---
title: "Client/server coming and going with custom actions"
canonical_url: "https://www.nutrient.io/guides/docuvieware/other-technologies/rest-client-server-coming-and-going-with-custom-actions/"
md_url: "https://www.nutrient.io/guides/docuvieware/other-technologies/rest-client-server-coming-and-going-with-custom-actions.md"
last_updated: "2026-05-23T00:08:18.055Z"
description: "Implement a custom action in your ASP.NET Web API project to generate QR codes on documents using DocuVieware’s JavaScript API."
---

# Client/server coming and going with custom actions

> Before starting, complete the [serving DocuVieware through a REST API](https://www.nutrient.io/guides/docuvieware/other-technologies/serving-docuvieware-through-a-rest-api.md) guide.

This guide shows how to implement an action that draws a QR code on the current document with a specified value in a C# REST service project with ASP.NET Web API 2 from the.NET Framework.

**Requirements** —.NET Framework 4.6 or above

## Preparing your action client-side

Add and implement the JavaScript function that calls the `PostCustomServerAction` function from the DocuVieware JavaScript public API. It’s usually called by an `onclick` event on some other page element similar to a button:

```javascript

<script>
 function drawQRCode() {
 var codeValue = prompt("Enter the text to encode", "DocuVieware");
 if (codeValue!= null) {
 DocuViewareAPI.PostCustomServerAction("DocuVieware1", true, "drawQRCode", codeValue);
 }
 }
</script>

```

## Preparing your action server-side

Implement the method that actually draws the QR code on the open document. Add a `CustomActions.cs` class to your project with the following content:

```csharp

using System.Drawing;
using GdPicture14;
using GdPicture14.WEB;
namespace DocuViewareREST
{
 public class CustomActions
 {
 public static void DrawQrCode(CustomActionEventArgs e)
 {
 string barcodeValue = e.args.ToString();
 if (e.docuVieware.PageCount > 0)
 {
 // we need to check if the document is an image...
 if (e.docuVieware.GetDocumentType() == DocumentType.DocumentTypeBitmap)
 {
 int imageId;
 GdPictureStatus status = e.docuVieware.GetNativeImage(out imageId);
 if (status == GdPictureStatus.OK)
 {
 GdPictureImaging oGdPictureImaging = new GdPictureImaging();
 oGdPictureImaging.BarcodeQRWrite(imageId, barcodeValue,
 BarcodeQREncodingMode.BarcodeQREncodingModeUndefined,
 BarcodeQRErrorCorrectionLevel.BarcodeQRErrorCorrectionLevelH,
 0, 5, 4, 10, 10, 0, Color.Black, Color.Transparent);
 }
 else
 {
 e.message = new DocuViewareMessage("Error during get native image : " + status + ".",
 icon: DocuViewareMessageIcon.Error);
 }
 }
 else
 {
 //...or a PDF document
 if (e.docuVieware.GetDocumentType() == DocumentType.DocumentTypePDF)
 {
 GdPicturePDF oGdPicturePdf;
 GdPictureStatus status = e.docuVieware.GetNativePDF(out oGdPicturePdf);
 if (status == GdPictureStatus.OK)
 {
 oGdPicturePdf.SetOrigin(PdfOrigin.PdfOriginTopLeft);
 oGdPicturePdf.SetMeasurementUnit(PdfMeasurementUnit.PdfMeasurementUnitCentimeter);
 oGdPicturePdf.DrawBarcodeQrCode(barcodeValue,
 BarcodeQREncodingMode.BarcodeQREncodingModeUndefined,
 BarcodeQRErrorCorrectionLevel.BarcodeQRErrorCorrectionLevelH,
 0, 4, 1, 1, Color.Black);
 }
 else
 {
 e.message = new DocuViewareMessage("Error during get native PDF : " + status + ".",
 icon: DocuViewareMessageIcon.Error);
 }
 }
 }
 e.docuVieware.RedrawPage();
 }
 else
 {
 e.message = new DocuViewareMessage("Please load a document first.",
 icon: DocuViewareMessageIcon.Error);
 }
 }
 }
}

```

Now properly catch the DocuVieware custom action event in the `Global.asax.cs` file and implement the corresponding handler.

**Steps:**

1. In the `Application_Start` part, subscribe to the `CustomAction` event and redirect it to a private handler named `CustomActionsDispatcher`:

   ```csharp

   DocuViewareEventsHandler.CustomAction += CustomActionsDispatcher;
   ```

   From now on, each time the `PostCustomServerAction` JavaScript function is called client side, the `CustomAction` event is fired and caught to go into the `CustomActionsDispatcher` method.

2. Implement `CustomActionsDispatcher` to dispatch the action to the proper method according to the `e.actionName` value:

   ```csharp

   private static void CustomActionsDispatcher(object sender, CustomActionEventArgs e)
   {
    if ((e.actionName == "drawQRCode") && (e.args!= null))
    {
    CustomActions.DrawQrCode(e);
    }
   }
   ```

## Sending and receiving data with a custom action

Below is a closer look at the `PostCustomServerAction` JavaScript function:

```javascript

function PostCustomServerAction: function (docuViewareID, async, actionName, params, success, error)

```

There are two extra parameters that weren’t used in the previous example: `success` and `error`. These two callbacks run your own code on success or on error. They’re optional functions you write on your own depending on what you want to achieve.

The important part here is the `success` callback. Through this, you can retrieve a result from the server action.

**Steps:**

1. In your JavaScript `drawQRCode` function, change the parameters you’re sending, because it needs to contain the code value and the result. Call it `params` and use it in the `PostCustomServerAction` call together with the success callback that you define, as demonstrated below:

   ```javascript

   function drawQRCode() {
    var codeValue = prompt("Enter the text to encode", "DocuVieware");
    if (codeValue!= null) {
    var params = {
    Value: codeValue,
    Example: false
    };
    DocuViewareAPI.PostCustomServerAction("DocuVieware1", true, "drawQRCode", params, function(result){ console.log("result: " + JSON.stringify(result)); });
    }
   }
   ```

   From now on, each time the custom action is called and successful, the `result` JSON object is written to the console.

2. Define the structure of the new parameter in `CustomActions.cs`. It has to match the JavaScript object structure you previously defined in the `drawQRCode` function exactly:

   ```csharp

   internal class MyCustomActionParameters
   {
    public string Value { get; set; }
    public bool Example { get; set; }
   }
   ```

3. Set up the server-side handler. Change the Boolean value called `example` from `false` to `true`. In the end, your `CustomActions.cs` looks like the example shown below:

   ```csharp

   using System.Drawing;
   using GdPicture14;
   using GdPicture14.WEB;
   using Newtonsoft.Json;
   namespace DocuViewareREST
    {
    public class CustomActions
    {
    internal class MyCustomActionParameters
    {
    public string Value { get; set; }
    public bool Example { get; set; }
    }
    public static void DrawQrCode(CustomActionEventArgs e)
    {
    // we need to properly cast the parameters according to the internal class previously defined...
    MyCustomActionParameters myParameters = JsonConvert.DeserializeObject<MyCustomActionParameters>(e.args.ToString());
    //...so we can use its content
    string barcodeValue = myParameters.Value;
    if (e.docuVieware.PageCount > 0)
    {
    // we need to check if the document is an image...
    if (e.docuVieware.GetDocumentType() == DocumentType.DocumentTypeBitmap)
    {
    int imageId;
    GdPictureStatus status = e.docuVieware.GetNativeImage(out imageId);
    if (status == GdPictureStatus.OK)
    {
    GdPictureImaging oGdPictureImaging = new GdPictureImaging();
    oGdPictureImaging.BarcodeQRWrite(imageId, barcodeValue,
    BarcodeQREncodingMode.BarcodeQREncodingModeUndefined,
    BarcodeQRErrorCorrectionLevel.BarcodeQRErrorCorrectionLevelH,
    0, 5, 4, 10, 10, 0, Color.Black, Color.Transparent);
    }
    else
    {
    e.message = new DocuViewareMessage("Error during get native image : " + status + ".",
    icon: DocuViewareMessageIcon.Error);
    }
    }
    else
    {
    //...or a PDF document
    if (e.docuVieware.GetDocumentType() == DocumentType.DocumentTypePDF)
    {
    GdPicturePDF oGdPicturePdf;
    GdPictureStatus status = e.docuVieware.GetNativePDF(out oGdPicturePdf);
    if (status == GdPictureStatus.OK)
    {
    oGdPicturePdf.SetOrigin(PdfOrigin.PdfOriginTopLeft);
    oGdPicturePdf.SetMeasurementUnit(PdfMeasurementUnit.PdfMeasurementUnitCentimeter);
    oGdPicturePdf.DrawBarcodeQrCode(barcodeValue,
    BarcodeQREncodingMode.BarcodeQREncodingModeUndefined,
    BarcodeQRErrorCorrectionLevel.BarcodeQRErrorCorrectionLevelH,
    0, 4, 1, 1, Color.Black);
    }
    else
    {
    e.message = new DocuViewareMessage("Error during get native PDF : " + status + ".",
    icon: DocuViewareMessageIcon.Error);
    }
    }
    }
    e.docuVieware.RedrawPage();
    }
    else
    {
    e.message = new DocuViewareMessage("Please load a document first.",
    icon: DocuViewareMessageIcon.Error);
    }
    }
    }
   }
   ```

Each time the client-side button is clicked, the `result` parameter is sent server-side with `false` value, changed to `true`, and sent back to client-side to be displayed in the console.

## Related guides

- [Serving DocuVieware through a REST API](https://www.nutrient.io/guides/docuvieware/other-technologies/serving-docuvieware-through-a-rest-api.md)

- [Use and handling of the selection area](https://www.nutrient.io/guides/docuvieware/other-technologies/rest-use-and-handling-of-the-selection-area.md)

- [Custom snap-in implementation](https://www.nutrient.io/guides/docuvieware/other-technologies/rest-custom-snap-in-implementation.md)
---

## Related pages

- [DocuVieware guide for Blazor](/guides/docuvieware/other-technologies/docuvieware-tutorial-for-blazor.md)
- [Introduction](/guides/docuvieware/other-technologies.md)
- [How to set up and use DocuVieware with React](/guides/docuvieware/other-technologies/how-to-set-up-and-use-docuvieware-with-react.md)
- [Integrating DocuVieware in your Angular2 client application](/guides/docuvieware/other-technologies/integrating-docuvieware-in-your-angular2-client-application.md)
- [Integrating DocuVieware in your ASP.NET Core MVC Razor client application](/guides/docuvieware/other-technologies/integrating-docuvieware-in-your-asp-dotnet-core-mvc-razor-client-application.md)
- [Integrating DocuVieware in your Java client application](/guides/docuvieware/other-technologies/integrating-docuvieware-in-your-java-client-application.md)
- [Integrating DocuVieware in your AngularJS client application](/guides/docuvieware/other-technologies/integrating-docuvieware-in-your-angularjs-client-application.md)
- [Integrating DocuVieware in your JavaScript/jQuery client application](/guides/docuvieware/other-technologies/integrating-docuvieware-in-your-javascript-jquery-client-application.md)
- [Integrating DocuVieware into SharePoint 2019](/guides/docuvieware/other-technologies/integrating-docuvieware-into-sharepoint-2019.md)
- [Integrating DocuVieware in your PHP client application](/guides/docuvieware/other-technologies/integrating-docuvieware-in-your-php-client-application.md)
- [Integrating DocuVieware in your ASP.NET MVC Razor client application](/guides/docuvieware/other-technologies/integrating-docuvieware-in-your-asp-dotnet-mvc-razor-client-application.md)
- [Integrating DocuVieware in your Node.js client application](/guides/docuvieware/other-technologies/integrating-docuvieware-in-your-nodejs-client-application.md)
- [Custom snap-in implementation](/guides/docuvieware/other-technologies/rest-custom-snap-in-implementation.md)
- [Integrating DocuVieware with Electron](/guides/docuvieware/other-technologies/integrating-docuvieware-with-electron.md)
- [Use and handling of the selection area](/guides/docuvieware/other-technologies/rest-use-and-handling-of-the-selection-area.md)
- [Serving DocuVieware through a REST API](/guides/docuvieware/other-technologies/serving-docuvieware-through-a-rest-api.md)
- [Your first Angular 10 application with DocuVieware](/guides/docuvieware/other-technologies/your-first-angular-10-application-with-docuvieware.md)

