Backend API
        
    <div class="widget-container">
    <div>
        @await Html.PartialAsync("_ItemDragging", "PlannedTasks")
    </div>
    <div>
        @await Html.PartialAsync("_ItemDragging", "DoingTasks")
    </div>
</div>
<script>
    function onDragStart(e) {
        var items = e.component.option("items");
        e.itemData = items[e.fromIndex];
    }
    function onAdd(e) {
        var store = e.component.getDataSource().store(),
            values = e.itemData;
        values.sort = e.toIndex;
        store.insert(values).then(() => {
            var changes = [{ type: "insert", data: values }];
            store.push(changes);
        });
    }
    function onRemove(e) {
        var store = e.component.getDataSource().store(),
            key = e.itemData.ID;
        store.remove(key).then(() => {
            var changes = [{ type: "remove", key: key }];
            store.push(changes);
        });
    }
    function onReorder(e) {
        var store = e.component.getDataSource().store(),
            key = e.itemData.ID,
            data = { Sort: e.toIndex };
        store.update(key, data).then(() => {
            var changes = [{ type: "update", key: key, data: data }];
            store.push(changes);
        });
    }
</script>
        
        @model string
@(Html.DevExtreme().List()
    .ID(@Model)
    .Height(380)
    .DataSource(d => d.Mvc()
        .Controller("ListItemDraggingEditing")
        .Key("ID")
        .LoadAction(string.Format("Get{0}", @Model))
        .InsertAction(string.Format("Insert{0}", @Model))
        .UpdateAction(string.Format("Update{0}", @Model))
        .DeleteAction(string.Format("Delete{0}", @Model))
    )
    .DataSourceOptions(dso => dso.Paginate(false))
    .DataSourceOptions(o => o.ReshapeOnPush(true).Sort("Sort"))
    .RepaintChangesOnly(true)
    .DisplayExpr("Text")
    .ItemDragging(id => id
        .AllowReordering(true)
        .Group("tasks")
        .OnDragStart("onDragStart")
        .OnAdd("onAdd")
        .OnRemove("onRemove")
        .OnReorder("onReorder")
    )
)
        
        using DevExtreme.NETCore.Demos.Models.SampleData;
using Microsoft.AspNetCore.Mvc;
using System;
using System.Collections.Generic;
using System.Linq;
namespace DevExtreme.NETCore.Demos.Controllers {
    public class ListController : Controller {
        public ActionResult DragAndDrop() {
            return View();
        }
    }
}
        
        using DevExtreme.AspNet.Data;
using DevExtreme.AspNet.Mvc;
using DevExpress.Utils.Serializing.Helpers;
using DevExtreme.NETCore.Demos.Models;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Caching.Memory;
using System.Linq;
namespace DevExtreme.NETCore.Demos.Controllers.ApiControllers {
    [Route("api/[controller]/[action]")]
    public class ListItemDraggingEditingController : Controller {
        InMemoryListPlannedDataContext _plannedTasksData;
        InMemoryListDoingDataContext _doingTasksData;
        public ListItemDraggingEditingController(IHttpContextAccessor httpContextAccessor, IMemoryCache memoryCache) {
            _plannedTasksData = new InMemoryListPlannedDataContext(httpContextAccessor, memoryCache);
            _doingTasksData = new InMemoryListDoingDataContext(httpContextAccessor, memoryCache);
        }
        [HttpGet]
        public object GetPlannedTasks(DataSourceLoadOptions loadOptions) {
            return DataSourceLoader.Load(_plannedTasksData.ListItems, loadOptions);
        }
        [HttpGet]
        public object GetDoingTasks(DataSourceLoadOptions loadOptions) {
            return DataSourceLoader.Load(_doingTasksData.ListItems, loadOptions);
        }
        [HttpPost]
        public IActionResult InsertPlannedTasks(string values) {
            var listItem = new ListTaskItem();
            JsonPopulateObjectExtensions.PopulateObject(values, listItem);
            if(!TryValidateModel(listItem))
                return BadRequest(ModelState.GetFullErrorMessage());
            return InsertTask(listItem, _plannedTasksData);
        }
        [HttpPost]
        public IActionResult InsertDoingTasks(string values) {
            var listItem = new ListTaskItem();
            JsonPopulateObjectExtensions.PopulateObject(values, listItem);
            if(!TryValidateModel(listItem))
                return BadRequest(ModelState.GetFullErrorMessage());
            return InsertTask(listItem, _doingTasksData);
        }
        IActionResult InsertTask(ListTaskItem listItem, InMemoryListTasksDataContext<ListTaskItem> tasksData) {
            var sortedTasks = tasksData.ListItems.OrderBy(t => t.Sort);
            for(var i = listItem.Sort; i < tasksData.ListItems.Count; i++) {
                sortedTasks.ElementAt(i).Sort++;
            }
            tasksData.ListItems.Add(listItem);
            tasksData.SaveChanges();
            return Ok(listItem);
        }
        [HttpPut]
        public IActionResult UpdatePlannedTasks(int key, string values) {
            var listItem = _plannedTasksData.ListItems.First(a => a.ID == key);
            var oldOrderIndex = listItem.Sort;
            JsonPopulateObjectExtensions.PopulateObject(values, listItem);
            if(!TryValidateModel(listItem))
                return BadRequest(ModelState.GetFullErrorMessage());
            return UpdateTask(listItem, oldOrderIndex, _plannedTasksData);
        }
        [HttpPut]
        public IActionResult UpdateDoingTasks(int key, string values) {
            var listItem = _doingTasksData.ListItems.First(a => a.ID == key);
            var oldOrderIndex = listItem.Sort;
            JsonPopulateObjectExtensions.PopulateObject(values, listItem);
            if(!TryValidateModel(listItem))
                return BadRequest(ModelState.GetFullErrorMessage());
            return UpdateTask(listItem, oldOrderIndex, _doingTasksData);
        }
        IActionResult UpdateTask(ListTaskItem listItem, int oldOrderIndex, InMemoryListTasksDataContext<ListTaskItem> tasksData) {
            tasksData.ListItems.Remove(listItem);
            var sortedTasks = tasksData.ListItems.OrderBy(t => t.Sort);
            AdjustSort(listItem, oldOrderIndex, sortedTasks);
            tasksData.ListItems.Add(listItem);
            tasksData.SaveChanges();
            return Ok(listItem);
        }
        void AdjustSort(ListTaskItem listItem, int oldOrderIndex, IOrderedEnumerable<ListTaskItem> sortedTasks) {
            if(oldOrderIndex != listItem.Sort) {
                if(oldOrderIndex < listItem.Sort) {
                    for(var i = oldOrderIndex; i < listItem.Sort; i++) {
                        if(sortedTasks.ElementAt(i).Sort > 0) {
                            sortedTasks.ElementAt(i).Sort--;
                        }
                    }
                } else if(oldOrderIndex > listItem.Sort) {
                    for(var i = listItem.Sort; i < oldOrderIndex; i++) {
                        if(sortedTasks.ElementAt(i).Sort < sortedTasks.Count()) {
                            sortedTasks.ElementAt(i).Sort++;
                        }
                    }
                }
            }
        }
        [HttpDelete]
        public void DeletePlannedTasks(int key) {
            DeleteTask(key, _plannedTasksData);
        }
        [HttpDelete]
        public void DeleteDoingTasks(int key) {
            DeleteTask(key, _doingTasksData);
        }
        private void DeleteTask(int key, InMemoryListTasksDataContext<ListTaskItem> tasksData) {
            var listItem = tasksData.ListItems.First(a => a.ID == key);
            tasksData.ListItems.Remove(listItem);
            var sortedTasks = tasksData.ListItems.OrderBy(t => t.Sort);
            for(var i = listItem.Sort; i < tasksData.ListItems.Count; i++) {
                sortedTasks.ElementAt(i).Sort--;
            }
            tasksData.SaveChanges();
        }
    }
}
        
        using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Caching.Memory;
using System.Collections.Generic;
using System.Linq;
namespace DevExtreme.NETCore.Demos.Models {
    public class InMemoryListDoingDataContext : InMemoryListTasksDataContext<ListTaskItem> {
        public InMemoryListDoingDataContext(IHttpContextAccessor contextAccessor, IMemoryCache memoryCache)
            : base(contextAccessor, memoryCache) {
        }
        public override ICollection<ListTaskItem> ListItems => ItemsInternal;
        protected override IEnumerable<ListTaskItem> Source => SampleData.SampleData.ListDoingTasks.ToList<ListTaskItem>();
        protected override int GetKey(ListTaskItem item) => item.ID;
        protected override void SetKey(ListTaskItem item, int key) => item.ID = key;
    }
}
        
        using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Caching.Memory;
using System.Collections.Generic;
using System.Linq;
namespace DevExtreme.NETCore.Demos.Models {
    public class InMemoryListPlannedDataContext : InMemoryListTasksDataContext<ListTaskItem> {
        public InMemoryListPlannedDataContext(IHttpContextAccessor contextAccessor, IMemoryCache memoryCache)
            : base(contextAccessor, memoryCache) {
        }
        public override ICollection<ListTaskItem> ListItems => ItemsInternal;
        protected override IEnumerable<ListTaskItem> Source => SampleData.SampleData.ListPlannedTasks.ToList<ListTaskItem>();
        protected override int GetKey(ListTaskItem item) => item.ID;
        protected override void SetKey(ListTaskItem item, int key) => item.ID = key;
    }
}
        
        using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Caching.Memory;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.Json;
namespace DevExtreme.NETCore.Demos.Models {
    public abstract class InMemoryListTasksDataContext<T> {
        IHttpContextAccessor _contextAccessor;
        IMemoryCache _memoryCache;
        public InMemoryListTasksDataContext(IHttpContextAccessor contextAccessor, IMemoryCache memoryCache) {
            _contextAccessor = contextAccessor;
            _memoryCache = memoryCache;
        }
        protected ICollection<T> ItemsInternal {
            get {
                var session = _contextAccessor.HttpContext.Session;
                if(!session.IsAvailable)
                    throw new NotSupportedException("Session is required");
                var key = session.Id + "_" + GetType().FullName;
                return _memoryCache.GetOrCreate(key, entry => {
                    session.SetInt32("dirty", 1);
                    entry.SlidingExpiration = TimeSpan.FromMinutes(10);
                    return DeepClone(Source);
                });
            }
        }
        public abstract ICollection<T> ListItems { get; }
        protected abstract IEnumerable<T> Source { get; }
        public void SaveChanges() {
            foreach(var item in ItemsInternal.Where(i => GetKey(i) == 0))
                SetKey(item, ItemsInternal.Max(GetKey) + 1);
        }
        protected abstract int GetKey(T item);
        protected abstract void SetKey(T item, int key);
        static ICollection<T> DeepClone(IEnumerable<T> source) {
            return JsonSerializer.Deserialize<List<T>>(JsonSerializer.Serialize(source));
        }
    }
}
        
        using System;
using System.Collections.Generic;
using System.Linq;
namespace DevExtreme.NETCore.Demos.Models {
    public class ListTaskItem {
        public int ID { get; set; }
        public string Text { get; set; }
        public int Sort { get; set; }
    }
}
        
        using System;
using System.Collections.Generic;
using System.Linq;
namespace DevExtreme.NETCore.Demos.Models.SampleData {
    public partial class SampleData {
        public static IEnumerable<ListTaskItem> ListDoingTasks = new[] {
            new ListTaskItem {
                ID = 1,
                Text = "Prepare 2019 Financial",
                Sort = 0
            },
            new ListTaskItem {
                ID = 2,
                Text = "Prepare 2019 Marketing Plan",
                Sort = 1
            },
            new ListTaskItem {
                ID = 3,
                Text = "Update Personnel Files",
                Sort = 2
            },
            new ListTaskItem {
                ID = 4,
                Text = "Review Health Insurance Options Under the Affordable Care Act",
                Sort = 3
            }
        };
        public static IEnumerable<ListTaskItem> ListPlannedTasks = new[] {
            new ListTaskItem {
                ID = 5,
                Text = "New Brochures",
                Sort = 0
            },
            new ListTaskItem {
                ID = 6,
                Text = "2019 Brochure Designs",
                Sort = 1
            },
            new ListTaskItem {
                ID = 7,
                Text = "Brochure Design Review",
                Sort = 2
            },
            new ListTaskItem {
                ID = 8,
                Text = "Website Re-Design Plan",
                Sort = 3
            },
            new ListTaskItem {
                ID = 9,
                Text = "Rollout of New Website and Marketing Brochures",
                Sort = 4
            },
            new ListTaskItem {
                ID = 10,
                Text = "Create 2018 Sales Report",
                Sort = 5
            },
            new ListTaskItem {
                ID = 11,
                Text = "Direct vs Online Sales Comparison Report",
                Sort = 6
            },
            new ListTaskItem {
                ID = 12,
                Text = "Review 2018 Sales Report and Approve 2019 Plans",
                Sort = 7
            },
            new ListTaskItem {
                ID = 13,
                Text = "Submit Signed NDA",
                Sort = 8
            },
            new ListTaskItem {
                ID = 14,
                Text = "Update Revenue Projections",
                Sort = 9
            },
            new ListTaskItem {
                ID = 15,
                Text = "Review Revenue Projections",
                Sort = 10
            },
            new ListTaskItem {
                ID = 16,
                Text = "Comment on Revenue Projections",
                Sort = 11
            },
            new ListTaskItem {
                ID = 17,
                Text = "Scan Health Insurance Forms",
                Sort = 12
            },
            new ListTaskItem {
                ID = 18,
                Text = "Sign Health Insurance Forms",
                Sort = 13
            },
            new ListTaskItem {
                ID = 19,
                Text = "Follow up with West Coast Stores",
                Sort = 14
            },
            new ListTaskItem {
                ID = 20,
                Text = "Follow up with East Coast Stores",
                Sort = 15
            },
            new ListTaskItem {
                ID = 21,
                Text = "Submit Refund Report for 2019 Recall",
                Sort = 16
            },
            new ListTaskItem {
                ID = 22,
                Text = "Give Final Approval for Refunds",
                Sort = 17
            },
            new ListTaskItem {
                ID = 23,
                Text = "Prepare Product Recall Report",
                Sort = 18
            },
            new ListTaskItem {
                ID = 24,
                Text = "Review Product Recall Report by Engineering Team",
                Sort = 19
            },
            new ListTaskItem {
                ID = 25,
                Text = "Review Training Course for any Omissions",
                Sort = 20
            },
            new ListTaskItem {
                ID = 26,
                Text = "Review Overtime Report",
                Sort = 21
            },
            new ListTaskItem {
                ID = 27,
                Text = "Submit Overtime Request Forms",
                Sort = 22
            },
            new ListTaskItem {
                ID = 28,
                Text = "Overtime Approval Guidelines",
                Sort = 23
            },
            new ListTaskItem {
                ID = 29,
                Text = "Create Report on Customer Feedback",
                Sort = 24
            },
            new ListTaskItem {
                ID = 30,
                Text = "Review Customer Feedback Report",
                Sort = 25
            }
        };
    }
}
        
        .widget-container {
    display: flex;
}
.widget-container > * {
    height: 400px;
    width: 50%;
    padding: 10px;
}
.dx-scrollview-content {
    min-height: 380px;
}
        
                The following steps describe how to configure this functionality:
- 
Enable item drag and drop 
 Set the itemDragging.allowReordering to true.
- 
Add the lists to the same group 
 Set the group property of both components to the same value to allow a user to drag and drop items between them.
- 
Reorder list items in code 
 Use the onDragStart event handler to store the dragged item's data. When a user drops the item, the onRemove and onAdd functions allow you to remove the item from its initial position and add it to the new location.