简体   繁体   中英

Using JavaScript to call a Controller Function in an MVC project

I'm working on an MVC ASP.NET core project with EF 6 which stores product data in a database and creates a processing and shipping list. An important feature of the project is for certain users to be able to change the order of this list manually, which I'm implementing using drag&drop cards. Each card is created by looping through an IEnumerable of the model in the View, with each

  • containing a partial which renders the card. The issue I'm having is that changing the order in the view doesn't inherently change the Product.Order attribute in the project. I need a way to access the model item of the card being moved and the model item.Order of the card being usurped inside the JavaScript drop function I have.

    I'm currently trying with var order = @Html.Raw(JsonConvert.SerializeObject(item.Order) as String);, but that doesn't seem to be exposing anything to JavaScript that I can work with. I have a second line exposing the entire object.

    Controller Method:

     public void ChangeOrder(Product p, int order) { //This creates a list of all of the jobs in the database sorted by descending Order var PList = from prod in _context.Products select prod; PList = PList.OrderByDescending(prod => prod.Order); int origin = p.Order; p.Order = order; if(origin > order) { int it = order; while (it < origin && it < PList.Count()) { PList.ElementAt(it++).Order--; } } else if(origin < order) { int it = origin; while (it < order && it < PList.Count()) { PList.ElementAt(it++).Order--; } } else { return; } } 

    Index View

     @using Newtonsoft.Json; @model IEnumerable<Project.Models.Product> @{ ViewData["Title"] = "Index"; } <h2>Index</h2> @*The list container*@ <ul class="container" id="dragfield" style="width: 100%;"> @*The first card is a minicontainer for the create partial view*@ <li class="card popupsrc" onclick="callPopup">...</li> @foreach (var item in Model) { <li class="dragcard" draggable="true" style="float: left; padding: 8px">@item.Order @*For debugging purposes, this displays the order with the card*@ @*THE FOLLOWING LINEs ARE NOT SECURED AND SHOULD BE CHANGED BEFORE PUBLISHING - FOR TESTING PURPOSES ONLY*@ var order = @Html.Raw(JsonConvert.SerializeObject(item.Order) as String); var order = @Html.Raw(JsonConvert.SerializeObject(item) as String); <partial name="_ProductCard.cshtml" model="item" /> </li> } </ul> 

    site.js Drag & Drop Block

     //D&D Functions Start { var dragSrcElem = null; function dragStartHandler(event) { // Target (this) element is card being dragged. dragSrcElem = this; event.dataTransfer.effectAllowed = 'move'; event.dataTransfer.setData('text/html', this.outerHTML); this.classList.add('dragElem'); } function dragOverHandler(event) { if (event.preventDefault) { event.preventDefault(); //Enables dropping } this.classList.add('over'); event.dataTransfer.dropEffect = 'move'; return false; } function dragEnterHandler(event) { // this|event.target is the card being hovered over. } function dragLeaveHandler(event) { this.classList.remove('over'); // this|e.target is card previously hovered over. } function handleDrop(event) { // this/e.target is card about to be usurped. if (event.stopPropagation) { event.stopPropagation(); // Prevents browsers from redirecting and cancelling the drag&drop } // If the card hasn't moved, do nothing if (dragSrcElem != this) { // Set the original card's HTML to the HTML of the card we dropped on this.parentNode.removeChild(dragSrcElem); var dropHTML = event.dataTransfer.getData('text/html'); this.insertAdjacentHTML('beforebegin', dropHTML); //refocuses to the original card var dropElem = this.previousSibling; //LOCATION OF ISSUE //call the Controller function to change the Order Attribute of the relocated card's item PFS.Controllers.ChangeOrder(dropElem, this.order); //LOCATION OF ISSUE addDnDHandlers(dropElem); } this.classList.remove('over'); return false; } function dragEndHandler(event) { // this|e.target is the original card. this.classList.remove('over'); } function addDnDHandlers(elem) { elem.addEventListener('dragstart', dragStartHandler, false); elem.addEventListener('dragenter', dragEnterHandler, false) elem.addEventListener('dragover', dragOverHandler, false); elem.addEventListener('dragleave', dragLeaveHandler, false); elem.addEventListener('drop', dropHandler, false); elem.addEventListener('dragend', dragEndHandler, false); } var jc = document.querySelectorAll('#dragcard .dragcard'); [].forEach.call(jc, addDnDHandlers); } //D&D Functions End 

    I expect the JavaScript handleDrop function to call a function in the controller using parameters from the view which originally called the JS function. Currently the code I have implemented in the view does not expose the necessary information to the Javascript code in a way I know how to access, nor does JS recognize the Controller function

  • From your JavaScript code, I'm not sure what exactly PFS is in the context of PFS.Controllers.ChangeOrder... so I'm not sure I could help there.

    Personally, when I try to reach a controller action, I like to JavaScript's built-in fetch function. Essentially, you pass in the url as a parameter and an object if you want to specify any other details (like a body or something). It looks something like this:

    //Of course you should replace this with your actual url, this one is just for demo //purposes.
    const changeOrderUrl = "order/ChangeOrder"; 
    
    fetch(changeOrderUrl, {
        method: "POST", //or GET or whatever your controller action is
        body: JSON.stringify({
            p: dropElem,
            order: this.order
        }),
        headers: { "content-type": "application/json; charset=utf-8" }
    })
    .then(response => response.json())
    .then((responseData) => {
        //Do whatever you want with the response here. IF you don't want to do anything with 
        //the response, you can remove both of the .then()'s
    });
    

    Additionally, you'll most likely have to add a [FromBody] attribute to the controller action's parameters like this: public void ChangeOrder([FromBody]Product p, int order)

    Let me know if I can assist in any other way!

    The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

     
    粤ICP备18138465号  © 2020-2024 STACKOOM.COM