简体   繁体   中英

PUT Ajax request returning 404 not found asp.net MVC

I am new to asp.net MVC, I am making one project just like stack overflow. In this, I just want to use the ajax system to upvote or down-vote the answer. So, I can show the counter increase and decrease without refreshing the page. I have default scaffolding one controller of Question in the controller and in which I have QuitionDetails method which is responsible for the QuitionDetailsView and in this view I am making ajax request to my API controller VotesController when the user clicks on the up-vote or down-vote. But I am getting this error

jquery-3.3.1.js:9600 PUT https://localhost:44389/Question/QuestionDetails/api/votes/3 404 not found
send @ jquery-3.3.1.js:9600
ajax @ jquery-3.3.1.js:9206
(anonymous) @ 2:230
dispatch @ jquery-3.3.1.js:5183
elemData.handle @ jquery-3.3.1.js:4991

here is my first default scaffolding controller Question

public ActionResult QuestionDetails(int Id)
        {
            QuestionDetailViewModel questionDetailViewModel = new QuestionDetailViewModel
            {
                Question = QBL.GetQuestions(Id),
                UserId = User.Identity.GetUserId(),
                QuestionId = Id,
            };
            return View(questionDetailViewModel);
        }
        [HttpPost]
        [ValidateInput(false)]
        public ActionResult QuestionDetails(QuestionDetailViewModel questionDetailViewModel)
        {
            QBL.CreateAnswer(questionDetailViewModel);
            return RedirectToAction("QuestionDetails", new { Id = questionDetailViewModel.QuestionId });
        }

View Code is as Below

@model AskMe.Models.ViewModel.QuestionDetailViewModel

@{
    ViewBag.Title = "QuestionDetails";
}

<h1>Question Details: </h1>
<h3>@Model.Question.Post.Title</h3>
@Html.Raw(Model.Question.Post.Content)
<hr />
<h3>Answers:</h3>
@foreach (var answer in Model.Question.Answers)
{
    <div class="card bg-light m-1">
        <div class="card-body">
            <h5 class="card-title">Answered by: @answer.Post.CreatedBy.UserName</h5>
            @Html.Raw(answer.Post.Content)
        </div>
        <div id="vote" class="col">
            <div>
                <button data-vote-id="@answer.Post.PostId" class="nav-link thumbs-up" href=""><i class="fa fa-thumbs-up" aria-hidden="true"></i></button>
            </div>
            <div>

            </div>
            <div>
                <button data-vote-id="@answer.Post.PostId" class="nav-link thumbs-down" href=""><i class="fa fa-thumbs-down" aria-hidden="true"></i></button>
            </div>
        </div>
    </div>
}
@using (Html.BeginForm())
{

    @Html.AntiForgeryToken()

    <div class="form-horizontal">
        <h3>Contribute your answer: </h3>
        <hr />
        @Html.ValidationSummary(true, "", new { @class = "text-danger" })

        <div class="form-group">
            @Html.LabelFor(m => m.AnswerContent, new { @class = "col-md-2 control-label" })
            <div class="col-md-10">
                @Html.TextAreaFor(m => m.AnswerContent, new { @class = "form-control" })
            </div>
        </div>

        <div class="form-group">
            <div class="col-md-offset-2 col-md-10">
                @Html.HiddenFor(m => m.UserId)
                @Html.HiddenFor(m => m.QuestionId)
                <input type="submit" value="Contribute now" class="btn btn-outline-primary" />
            </div>
        </div>
    </div>
}
@section Scripts {
    @Scripts.Render("~/bundles/jqueryval");

    <script type="text/javascript">
        $(document).ready(function () {
            tinyMCE.init({
                mode: "textareas",
            });

            $("#vote").on("click",".thumbs-up", function () {
                console.log("in selection func");
                $.ajax({                   
                url: "api/vote/" + $(this).attr("data-vote-id"),
                method: "PUT",
                success: function () {
                    console.log("success");
                }
            })
        })

        });
    </script>

}

And here is my votes API controller code

using AskMe.Models;
using Microsoft.AspNet.Identity;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web.Http;

namespace AskMe.API
{
    public class VotesController : ApiController
    {
        ApplicationDbContext _context = new ApplicationDbContext();

        [HttpPut]
        public IHttpActionResult UpVote(int postId)
        {
            var userId = User.Identity.GetUserId();
            var user = _context.Users.Find(userId);
            var post = _context.Posts.Find(postId);
            var votes = post.Votes.ToList();
            if (votes.FindAll(u => u.UserId == userId).Count == 0)
            {
                Votes vote = new Votes
                {
                    VotedDateTime = DateTime.Now,
                    UserId = userId,
                    User = user,
                    Post = post,
                    PostId = postId,
                };
                post.Votes.Add(vote);
                _context.SaveChanges();
                return Ok();
            }
            return BadRequest();
        }
    }
}

I am not sure my api link should be like this https://localhost:44389/Question/QuestionDetails/api/votes/3 or https://localhost:44389/api/votes/3 and my route config is routes.MapRoute( name: "Default", url: "{controller}/{action}/{id}", defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional } );

If you haven't changed the standard routing, you need to include the action/method name in your ajax call.

Try:

url: "api/vote/upvote/" + $(this).attr("data-vote-id")

Your route configuration should look like this:

            config.Routes.MapHttpRoute(
                name: "DefaultApi",
                routeTemplate: "api/{controller}/{id}",
                defaults: new { id = RouteParameter.Optional }
            );

If you are using MVC5 with WebApi, which is my guess, you have to be careful. See this post for further information on how to do it.

Actually your error telling everything. When you requesting for 'UpVote' action it's looking into "basepath(localhost)/controller/action/Api/etc." and it does not exits. You must create request for https://localhost:44389/API/Votes/UpVote/3

If you want to call controller action from ajax, you have to mention the controller name and action method in url section of ajax call.

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