# Create a custom endpoint

## Overview

With Sitefinity OData web services, you can use the headless API, the AdminApp UI, and the ASP.NET Core Renderer application to create, retrieve, update and delete data from Sitefinity CMS.

If your business needs require logic that is not provided out-of-the-box, you can create a custom web services endpoint and consume data through it. This tutorial describes how to create, register, and call a web service with your custom logic.

## Procedure

The steps that you need to execute to create a custom endpoint that calls a method with your own logic are the following:

1. Create a class that implements the `IOperationProvider` interface.\
   In this tutorial – `MyCustomOperationProvider` class.
2. Create a custom method that you can call by an HTTP request to the required URL.\
   In this tutorial – `MyCustomMethod`.
3. Register the method as an operation, using the `GetOperations` class, so that OData can recognize it and make it available in the API.
4. Register the created class in the `ObjectFactory`, so that it can be resolved runtime.\
   In this tutorial, you register the `MyCustomOperationProvider` class in the `Global.asax` class of your application.
5. Call the custom endpoint.

## Implement IOperationProvider interface

Sitefinity CMS provides the `IOperationProvider` interface that you must implement to create a custom endpoint.

> info  **NOTE**: You can have multiple implementations of this interface.

First, you create a class that implements this interface.\
In this tutorial, you create a class named `MyCustomOperationProvider`.\
See the code sample below.

The `IOperationProvider` interface has one method - `GetOperations()` that you must implement.\
The purpose of this implementation is to provide operations to Sitefinity CMS. An operation is the method that is executed when you call an endpoint, together with metadata for the endpoint, such as URL, request type, and request parameters. Sitefinity CMS collects the operations and registers them as OData web service endpoints.

## Create the method with your custom logic

Inside `MyCustomOperationProvider` class, you create the method that will hold your custom logic. This method is called when you hit the custom endpoint.\
In this tutorial, create a method and call it `MyCustomMethod`.

### MyCustomMethod

The method returns custom values and accepts custom parameters.\
If your method accepts any parameters, the first one must always be of type `OperationContext`. This parameter is automatically passed by Sitefinity CMS and contains information about the request.

The rest of the parameters can be:

* Primitive - when making `GET` and `POST` requests
* Complex objects – when making a `POST` request and you pass a request body.

In this tutorial, `MyCustomMethod` accepts:

* A `context` parameter of type `OperationContext`\
  Automatically passed to the method by Sitefinity CMS
* A `data` parameter of type `string`\
  Provided when calling the web service endpoint.

The method can return one of the following:

* No value\
  For example, when you execute a `POST` request that has no response
* A primitive
* An object
* A collection

In this tutorial, `MyCustomMethod` returns a collection of `MyResponseDTO` objects with two properties.\
See the code sample below.

### MyResponseDTO

Create a DTO and name it `MyResponseDTO`.\
Inside the `MyResponseDTO` class, create two properties of type string – `Id` and `Data`.

The class and its properties have to be decorated with the `DataContract` and `DataMember` attributes, so that they can be serialized and deserialized.

## Register the method as an operation

You register your custom method as operation, by implementing the `GetOperations` method of the `IOperationProvider` interface. This way, Sitefinity CMS can create an endpoint, based on your custom method.

The `GetOperations` method returns an `IEnumerable` of `OperationData` objects. This way, you can register multiple custom endpoints, using one operations provider class.

The `OperationData` class has a set of static functions that you can use to create an `OperationData` object from the method that you previously implemented.

### Parameters

The `GetOperations` method accepts a parameter - `clrType`.\
The value of the parameter is the CLR type corresponding to the OData entity type. You use this parameter to register the custom operation for a particular type(s).\
In this tutorial – `NewsItem`.

### Properties

When implementing the `OperationData` class, there are the following properties that you can use to modify the endpoint:

* `OperationType`\
  Indicates the type of the registered operation.  It can be one of the following:
  * `Collection` – the operation targets an entity set
  * `PerItem` – the operation targets a particular entity item
  * `Unbound` – the operation is not bound to any entity type.\
    This is the default value.
* `IsAllowedUnauthorized`\
  This parameter is Boolean and indicating whether unauthorized users can make requests to the endpoint.\
  If set to `false`, the access restriction will be the same as for the whole service.\
  The default value is `false`.
* `IsRead`\
  This property is a Boolean value indicating whether the endpoint accepts:
  * `GET` requests, if set to `true`.\
    This is the default value.
  * `POST` requests, if set to `false`.

In this tutorial, the custom endpoint:

* Targets a particular item of type `NewsItem` (`OperationType` = `PerItem`)
* Allows unauthorized access (`IsAllowedUnauthorized` = `true`)
* Is executed by a `POST` request (`IsRead` = `false`)

## Code sample

The following code sample displays how to implement the IOperationProvider interface, create your custom method and DTO, and register the method as an operation with the `GetOperations` method of the `OperationData` class:

```C#
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using Telerik.Sitefinity.News.Model;
using Telerik.Sitefinity.Web.Services.Contracts.Operations;

namespace SitefinityWebApp
{
   public class MyCustomOperationProvider : IOperationProvider
   {
       public IEnumerable<OperationData> GetOperations(Type clrType)
       {
           if (typeof(NewsItem).IsAssignableFrom(clrType))
           {
               var myCustomOperation = OperationData.Create<string, IEnumerable<MyResponseDTO>>(this.MyCustomMethod);
               myCustomOperation.OperationType = OperationType.PerItem;
               myCustomOperation.IsAllowedUnauthorized = true;
               myCustomOperation.IsRead = false;

               return new OperationData[] { myCustomOperation };
           }

           return Enumerable.Empty<OperationData>();
       }

       private IEnumerable<MyResponseDTO> MyCustomMethod(OperationContext context, string data)
       {

           // Custom logic here...

           var itemKey = context.GetKey();

           return new List<MyResponseDTO>
           {
               new MyResponseDTO()
               {
                   Id = itemKey,
                   Data = "SomeData = " + data
               }
           };
       }
   }

   [DataContract]
   public class MyResponseDTO
   {
       [DataMember]
       public string Id { get; set; }

       [DataMember]
       public string Data { get; set; }

   }
}
```

## Register the operation provider

After implementing the `GetOperations` method in `MyCustomOperationProvider` class, you must register the class in the `ObjectFactory`. This way, it can be instantiated runtime and provide operations data to Sitefinity CMS.

To register the class in the `Global.asax` on application start, use the following code sample:

```C#
using System;
using Telerik.Microsoft.Practices.Unity;
using Telerik.Sitefinity.Abstractions;
using Telerik.Sitefinity.Web.Services.Contracts.Operations;

namespace SitefinityWebApp
{
   public class Global : System.Web.HttpApplication
   {

       protected void Application_Start(object sender, EventArgs e)
       {
           ObjectFactory.RegisteringIoCTypes += (object s, EventArgs args) =>
           {
               ObjectFactory.Container.RegisterType(typeof(IOperationProvider), typeof(MyCustomOperationProvider), typeof(MyCustomOperationProvider).Name);
           };
       }
   }
}
```

## Call the custom endpoint

The way you call a custom web service is determined by the way you have registered your method via the `OperationData` class, as well as the name of the class that holds the custom logic.

The URL of the endpoint is based on a naming convention:\
`{baseurl}/api/default/{path}/Default.{method_name}()`

For example, if the method created is named `MyCustomMethod` the URL will be:\
`{baseurl}/api/default/{path}/Default.MyCustomMethod()`

Depending on how you have registered the operations, the call to the endpoint can be the following:

* If the `OperationType`is:
  * `Collection`:\
    `{baseurl}/api/default/{entity_type}/Default.MyCustomMethod()`
  * `PerItem`:\
    `{baseurl}/api/default/{entity_type}({item_id})/Default.MyCustomMethod()`
  * `Unbound`:\
    `{baseurl}/api/default/Default.MyCustomMethod()`
* If `IsAllowedUnauthorized` is `false` and the service access is different from anonymous, you must pass an `Authorization` header with the request.
* If `IsRead` is:
  * `true` – the operations parameters are passed in a `GET` request, in the brackets, after the operation name in the URL:\
    `GET {baseurl}/api/default/Default.MyCustomMethod(data='Some data')`
  * `false` – the operations parameters are passed in a `POST` request in the request body\
    `{"data": "Some data"}`

In this tutorial, to call your custom endpoint, execute a the following request and pass the request body.

**Sample request**

> success **POST** `http://mysite.com/api/default/newsitems(f1aef86e-c13f-459b-a318-23bf8c507fe9)/Default.MyCustomMethod()`

**Request body**

```JSON
{
 "data": "123"
}
```

**Sample response**

```JSON
{
  "value": [
    {
      "Id": "f1aef86e-c13f-459b-a318-23bf8c507fe9",
      "Data": "SomeData = 123"
    }
  ]
}
```
