# ForeignKey Column

Use the ForeignKey column to map the value of a bound field to display text from a collection outside the Grid. This behavior follows the SQL foreign key pattern for linking related data.

## ForeignKey Column Data Binding

You can supply the foreign values for the columns of the Grid using the following approaches:

* [Binding to a local data collection](https://www.telerik.com/aspnet-mvc/documentation/html-helpers/data-management/grid/columns/foreignkey-column#binding-to-local-data)
* [Binding to remote data](https://www.telerik.com/aspnet-mvc/documentation/html-helpers/data-management/grid/columns/foreignkey-column#binding-to-remote-data)

### Binding to Local Data

To implement a ForeignKey column in the Grid that binds to a local data collection of items, pass a valid `IEnumerable` collection to the [`ForeignKey()`](https://www.telerik.com/aspnet-mvc/documentation/api/kendo.mvc.ui.fluent/gridcolumnfactory#foreignkeysystemlinqexpressionsexpressionsystemcollectionsienumerablesystemstringsystemstring) column configuration.

The example below shows the following ForeignKey column declaration:

* The column binds to the `CategoryID` field.
* The column uses a local `IEnumerable` collection received from the controller through a `ViewData`.
* The model property, which stores the data value field, is `CategoryID`.
* The model property, which stores the data text field, is `CategoryName`.

```Razor HtmlHelper
columns.ForeignKey(p => p.CategoryID, (System.Collections.IEnumerable)ViewData["categories"], "CategoryID", "CategoryName").Title("Category").Width(200);
```

```C# Controller
public class GridController : Controller
{
    public ActionResult Index()
    {
        ViewData["categories"] = GetCategories();
        return View();
    }

    private IEnumerable<CategoryViewModel> GetCategories()
    {
        var dataContext = new DemoDBContext();
        var categories = dataContext.Categories
            .Select(c => new CategoryViewModel {
                CategoryID = c.CategoryID,
                CategoryName = c.CategoryName
            })
            .OrderBy(e => e.CategoryName)
            .ToList();

        return categories;
    }
}
```

```C# ForeignKeyModel
public class CategoryViewModel{
    public int CategoryID { get; set; }
    public string CategoryName { get; set; }
}
```

For a live example, visit the [ForeignKey Column Demo of the Grid](https://demos.telerik.com/aspnet-mvc/grid/foreignkeycolumn).

### Binding to Remote Data

To bind the Grid column to a remote collection of items, specify a URL to the remote endpoint that returns the data instead of a static collection. You must supply the `dataFieldValue` and `dataFieldText` parameters so the column binds to the correct foreign key value.

The example below shows the following [`ForeignKey()`](https://www.telerik.com/aspnet-mvc/documentation/api/kendo.mvc.ui.fluent/gridcolumnfactory#foreignkeysystemlinqexpressionsexpressionsystemactionsystemstringsystemstring) column configuration:

* The column binds to the `CategoryID` field.
* The column uses a DataSource, which requests the data from the `Categories` action method on the server.
* The model property, which stores the data value field, is `CategoryID`.
* The model property, which stores the data text field, is `CategoryName`.

```Razor HtmlHelper
    columns.ForeignKey(p => p.CategoryID, ds => ds.Read(r => r.Action("Categories", "Grid")), "CategoryID", "CategoryName").Title("Category").Width(200);
```

```C# GridController.cs
public class GridController : Controller
{
    public JsonResult Categories()
    {
        var dataContext = new DemoDBContext();
        var categories = dataContext.Categories
        .Select(c => new CategoryViewModel
        {
            CategoryID = c.CategoryID,
            CategoryName = c.CategoryName
        })
        .OrderBy(e => e.CategoryName);

        return Json(categories, JsonRequestBehavior.AllowGet);
    }
}
```

```C# ForeignKeyModel
    public class CategoryViewModel{
        public int CategoryID { get; set; }
        public string CategoryName { get; set; }
    }
```

For a live example, visit the [ForeignKey Column Binding Demo of the Grid](https://demos.telerik.com/aspnet-mvc/grid/foreignkeycolumnbinding).

## ForeignKey Column Editor

The ForeignKey column supports a [built-in DropDownList editor](https://www.telerik.com/aspnet-mvc/documentation/html-helpers/data-management/grid/columns/foreignkey-column#default-editor) and a [custom editor](https://www.telerik.com/aspnet-mvc/documentation/html-helpers/data-management/grid/columns/foreignkey-column#custom-editor).

### Default Editor

By design, when the Grid is editable and contains a ForeignKey column, it builds an internal DropDownList editor template **GridForeignKey** located in the `~/Views/Shared/EditorTemplates/` folder.

```GridForeignKey.cshtml
@model object

@(
 Html.Kendo().DropDownListFor(m => m)
    .BindTo((SelectList)ViewData[ViewData.TemplateInfo.GetFullHtmlFieldName("") + "_Data"])
    .HtmlAttributes(new { title = Html.ViewContext.ViewData.TemplateInfo.GetFullHtmlFieldName("")})
)
```

To enable the default **GridForeignKey** editor when the Grid is set up for [Popup](https://www.telerik.com/aspnet-mvc/documentation/html-helpers/data-management/grid/editing/popup) editing, decorate the model property bound in the ForeignKey column with the `UIHint` data attribute and specify the name of the view that contains the default editor (**GridForeignKey**):

```C# GridModel
public class ProductViewModel
{
    public int ProductID { get; set; }
    [UIHint("GridForeignKey")]
    public int CategoryID { get; set; }
}
```

```Razor GridForeignKey.cshtml
@model object

@(
 Html.Kendo().DropDownListFor(m => m)
    .BindTo((SelectList)ViewData[ViewData.TemplateInfo.GetFullHtmlFieldName("") + "_Data"])
    .HtmlAttributes(new { title = Html.ViewContext.ViewData.TemplateInfo.GetFullHtmlFieldName("")})
)
```

```Razor HtmlHelper
columns.ForeignKey(p => p.CategoryID, (System.Collections.IEnumerable)ViewData["categories"], "CategoryID", "CategoryName").Title("Category").Width(200);
```

When the Grid is set up for [Inline](https://www.telerik.com/aspnet-mvc/documentation/html-helpers/data-management/grid/editing/inline) or [InCell](https://www.telerik.com/aspnet-mvc/documentation/html-helpers/data-management/grid/editing/batch) editing, the default ForeignKey column editor activates automatically when the row or cell enters edit mode.

### Custom Editor

To use a custom editor for the ForeignKey column, use the [`ForeignKey()` overload](https://www.telerik.com/aspnet-mvc/documentation/api/kendo.mvc.ui.fluent/gridcolumnfactory#foreignkeysystemlinqexpressionsexpressionsystemactionsystemstringsystemstringsystemboolean) and set its `useServerEditor` argument to `true` to indicate that a custom editor must be used.

> note To use a custom editor for the ForeignKey column in HtmlHelper Grid, configure the column for [remote data binding](https://www.telerik.com/aspnet-mvc/documentation/html-helpers/data-management/grid/columns/foreignkey-column#binding-to-remote-data).

The following example shows how to create a custom editor for a ForeignKey column in an editable HtmlHelper Grid:

1. Define a ForeignKey column in the Grid by using the [remote data-binding approach](https://www.telerik.com/aspnet-mvc/documentation/html-helpers/data-management/grid/columns/foreignkey-column#binding-to-remote-data) and set the last argument to `true`:

   ```Razor HtmlHelper
   columns.ForeignKey(p => p.ProductId, ds => ds.Read(r => r.Action("GetProducts", "Home")), "ProductId", "ProductName", true);
   ```

2. Add a view that contains the desired editor in the `~/Views/Shared/EditorTemplates/` folder:

   ```Razor CustomFKeyEditor.cshtml
   @model object

   @(Html.Kendo().DropDownListFor(m => m)
       .Filter("contains")
       .DataTextField("ProductName")
       .DataValueField("ProductId")
       .DataSource(d => d.Read(r => r.Action("GetProducts", "Home")).ServerFiltering(false))
   )
   ```

   ```C# HomeController.cs
   public JsonResult GetProducts()
   {
       var northwind = new DemoDBContext();
       var products = northwind.Products.Select(product => new ProductViewModel
       {
           ProductId = product.ProductId,
           ProductName = product.ProductName
       });
       return Json(products, JsonRequestBehavior.AllowGet);
   }
   ```

   ```C# ForeignKeyModel
   public class ProductViewModel
   {
       public int ProductId { get; set; }
       public string ProductName { get; set; }
   }
   ```

3. If the Grid is set up for InCell or Popup editing, decorate the `ProductId` property with the `UIHint` data attribute and specify the name of the view that contains the custom editor (**CustomFKeyEditor**). If the Grid is configured for Inline editing, use the [`EditorTemplateName()`](https://www.telerik.com/aspnet-mvc/documentation/api/kendo.mvc.ui.fluent/gridboundcolumnbuilder#editortemplatenamesystemstring) option to specify the custom editor.

   ```C# InCell_Popup_editing
   public class GridViewModel
   {
       [UIHint("CustomFKeyEditor")]
       public int ProductId { get; set; }
   }
   ```

   ```Razor Inline_editing
   columns.ForeignKey(p => p.ProductId, ds => ds.Read(r => r.Action("GetProducts", "Home")), "ProductId", "ProductName", true).EditorTemplateName("CustomFKeyEditor");
   ```

4. Specify the default value for the ForeignKey field in the `Model()` configuration of the DataSource. It will be used when adding a new record to the Grid.

   ```Razor HtmlHelper
       .DataSource(dataSource => dataSource
           .Ajax()
           .Model(model =>
           {
               model.Id(p => p.Id);
               model.Field(p => p.Id).Editable(false);
               model.Field(p => p.ProductId).DefaultValue(1);
           })
           // Additional configuration.
       )
   ```

## See Also

* [Foreign Key Column Local Binding (Demo)](https://demos.telerik.com/aspnet-mvc/grid/foreignkeycolumn)
* [Foreign Key Column Remote Binding (Demo)](https://demos.telerik.com/aspnet-mvc/grid/foreignkeycolumnbinding)
* [Server-Side HtmlHelper API](https://www.telerik.com/aspnet-mvc/documentation/api/grid)
