1

I'm using the following code to call a partial view:

$('#btnGetMilestones').click(function () {
$.ajax({
    url: "GetMilestones",
    type: "get",
    success: function (result) {
        $('#milestonesContainer').html(result);
    },
    error: function (xhr, status, error) {
        var msg = "Response failed with status: " + status + "</br>"
        + " Error: " + error;
        $('#milestonesContainer').html(msg);
    },
    complete: function (xhr, status) {
        var doneMsg = "Operation complete with status: " + status;
        alert(doneMsg);
    }
});

});

for this ActionResult:

public PartialViewResult GetMilestones()
    {
        return PartialView("_GetMilestones");
    }

The partial view has the milestones for a project (milestones and project are models). When I call the partial view like this:

<div id="milestonesContainer">
    @Html.Partial("_GetMilestones")
</div>

it works fine, it gets all the milestones for the project. But when I try to call the partial view via ajax, the error gets called: Response failed with status: error

Error: Bad Request

I'm in the details view of a projects so the url is like this http://localhost:55623/Projects/Details/2002

I'm new in ajax and javascript, so please if possible, explain me like you do to a beginner.

UPDATE:

After getting some answer and playing around to find a solution, I understand why the error appears. I'm inside the details view, so the url is like this: http://localhost:55623/Projects/Details/2002 see there is an ID parameter. When I make the ajax call, the url is like this http://localhost:55623/Projects/Details without the id parameter. So in return I get a 400 error code

Arianit
  • 543
  • 2
  • 8
  • 24
  • 1
    Possible duplicate of [How to render partial view in MVC5 via ajax call to a controller and return HTML](http://stackoverflow.com/questions/32610270/how-to-render-partial-view-in-mvc5-via-ajax-call-to-a-controller-and-return-html) – Heretic Monkey Oct 20 '16 at 14:42
  • Unless your currentl url is`http:///`, your url is incorrect. It needs to be `//GetMilestones`. – Gavin Oct 20 '16 at 14:46
  • @MikeMcCaughan no it isn't – Arianit Oct 20 '16 at 14:46
  • 1
    Perhaps you could read the question and its answers, then [edit] your question to show it is not a duplicate. Please read [this meta post about contesting duplicates](http://meta.stackoverflow.com/q/252252/215552). – Heretic Monkey Oct 20 '16 at 14:51
  • @Gavin the url must be like this: http://localhost:xcxx/Details/12 – Arianit Oct 20 '16 at 14:54
  • @MikeMcCaughan it's not answered. I checked the questions before I made my own, and non had the answer to my problem. – Arianit Oct 20 '16 at 15:55
  • Are you sure that is from url? Can you try as url:/Controller/GetMilestones, but dont forget to put contenttype as html and datatype html. Sorry I cant provide an example now because I'm @ phone – Ermir Beqiraj Oct 20 '16 at 16:42
  • 1
    @Arianit You can pass data with AJAX calls too. `url: ..., type: ..., data: ...` – Gavin Oct 20 '16 at 16:45
  • @Gavin yes, I'm trying to do that now – Arianit Oct 20 '16 at 16:50
  • @Arianit Your code doesn't show any parameter for `GetMilestones()`, but does it actually take an id? If so, you can just add `data: { id: }` to your ajax. – Gavin Oct 20 '16 at 17:39
  • tried that but didn't work @Gavin – Arianit Oct 20 '16 at 17:45
  • Have you tried `url: /Projects/GetMilestones/`? – Gavin Oct 20 '16 at 17:47

5 Answers5

2

Instead of url: "GetMilestones", try using url: "@Url.Action("GetMilestones")" which will render the actual relative path of the action i.e. /{Controller}/GetMilestones.

Also ensure that you are referring to the correct file name in your controller, as in your view you refer to "_GetMilestone" and you say that works, but in your controller you reference "_GetMilestones" which would not resolve if your filename is indeed "_GetMilestone"

If you're getting a 500 error, that means it's likely that you're hitting the action and an exception is occurring before or while it renders the partial view. Try navigating directly to the partial view's action in your browser by typing localhost:port/Projects/GetMilestones and see if an exception page appears. Make sure you do something like this in the Configure method of your Startup class:

public void Configure (IApplicationBuilder app) 
{    
    app.UseDeveloperExceptionPage();
}
Ceshion
  • 686
  • 1
  • 6
  • 17
  • shouldn't it be "@Url.Action('GetMilestones')" ? – Arianit Oct 20 '16 at 14:48
  • Nope! Since it's razor syntax (@), that means the following is a C# method call. In C#, single quotes are used for character literals. That being said, MVC understands when you put something like "@Class.Method("")" in a javascript block that only the part from @ to ) is C# and the rest is javascript. The result is that you render a string of characters `/Controller/GetMilestones` between two javascript double quotes, resulting in a javascript string literal `"/Controller/GetMilestones"` when rendering the document. – Ceshion Oct 20 '16 at 14:52
  • I wrote the ajax code in a separate js file. Now I wrote it inside the view, and not the error is: Internal Server Error – Arianit Oct 20 '16 at 14:57
  • Are you sure you're referring to your partial view by the correct name? I noticed in one place you reference _GetMilestones and in the other you reference _GetMilestone. – Ceshion Oct 20 '16 at 14:59
  • oh yes, it is cuz the one without the s in the end was to check if it works. I will edit it in the question so others don't get confused – Arianit Oct 20 '16 at 15:09
  • the url of the view before I click the button to call the ajax is: http://localhost:55623/Projects/Details/2002 and I think I must fix something about the route too, I think the ID parameter has something to do with the error – Arianit Oct 20 '16 at 15:26
  • Oh, my mistake, `localhost:port/Projects/GetMilestones`. Navigate to that URL and see if an exception page appears – Ceshion Oct 20 '16 at 15:30
  • Cannot perform runtime binding on a null reference Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code. Exception Details: Microsoft.CSharp.RuntimeBinder.RuntimeBinderException: Cannot perform runtime binding on a null reference – Arianit Oct 20 '16 at 15:33
  • Is your partial view looking for a model? – Ceshion Oct 20 '16 at 15:35
  • I updated the question, added some info... No the partial view is not looking for a model, but how I said, when I call the partial without the ajax call, but directly with @Html.Partial("_Milestones") I get the result I want. – Arianit Oct 20 '16 at 15:40
2

To build on my comment:

Sorry, I was being ambiguous with the term url. Here's what I meant:

Unless your currentl url in the browser is http://<hostname>/<Controller that contains GetMilestones>, your AJAX url is incorrect. The AJAX url needs to be /<Controller>/GetMilestones.

The beginning / takes you to the root of the project, then the rest is taken care of by your route config (typically /Controller/Method/Id). That's why the AJAX url usually needs to be /Controller/Method. However, if you are at the Index view, your url is typically http://<hostname>/Controller. So, if this is the case and your AJAX url is just Method, it will take you to http://<hostname>/Controller/Method since you didn't prepend your AJAX url with a /.

Gavin
  • 4,365
  • 1
  • 18
  • 27
  • the GetMilestones action is inside the the ProjectsController. I navigate to the details of the project, there is the button to call the partial view... I don't know if the id parameter has to do something with this error, but I have a similar project, where I tested if the ajax call works, and it works without problem, same code, except the elements in the view and without the id parameter. – Arianit Oct 20 '16 at 15:14
2

You should consider taking advantage of the helper methods like Url.Action to generate the correct relative path to the action method you want to call via ajax. If you are js code is inside the view, you can simply call the method like

url: "@Url.Action("GetMilestones","Project")",

If it is in an external js file, you can still use the helper method to generate the path and set it to a variable which your external js file. Make sure to do javascript namespacing when you do so to avoid possible overwriting of js global variables.

so in your view/layout you can do this

<script>
    var myApp = myApp || {};  
    myApp.Urls = myApp.Urls || {};     
    myApp.Urls.mileStoneUrl= '@Url.Action("GetMilestones","Project")';
</script>
<script src="~/Scripts/PageSpecificExternalJsFile.js"></script>

And in your PageSpecificExternalJsFile.js file, you can read it like

$(function(){
   $('#btnGetMilestones').click(function () {
      $.ajax({
           url: myApp.Urls.mileStoneUrl,
           //Your existing code goes here

           })
     });
});
Shyju
  • 214,206
  • 104
  • 411
  • 497
  • must this be in the _Layout view or in the view where I call the ajax? – Arianit Oct 20 '16 at 16:52
  • 1
    you can put it in either. If you are putting it in the individual vieww – Shyju Oct 20 '16 at 17:18
  • I like this way, but isn't it easier when using external js file to just write url: '/Projects/GetMilestones/' ? – Arianit Oct 20 '16 at 20:07
  • 1
    Using the helper methods will make sure that it will work in any hosting environment (Ex : `yourSite.someDomain.com/` etc). – Shyju Oct 20 '16 at 20:10
2

You need to change first url to something that match the route:

 '/<Controller>/GetMilestones/'

switch from PartialViewResult to ActionResult

go for ajax like:

url: "GetMilestones",
type: "get",
contentType: 'application/html; charset=utf-8',
dataType : 'html'
Ermir Beqiraj
  • 867
  • 11
  • 24
1

Thanks to all for answering. I got an answer for my problem, maybe it's kinda not expected. Her it is: change the ajax method:

$('#btnGetMilestones').click(function () { 
        $.ajax({
            url: '/Projects/GetMilestones/' + "?id=" + window.location.href.split('/').pop(),                
            type: "GET",
            success: function (data) {
                $('#milestonesContainer').html(data);
            },
            error: function (xhr, status, error) {
                var msg = "Response failed with status: " + status + "</br>"
                + " Error: " + error;
                $('#milestonesContainer').html(msg);
            },
            complete: function (xhr, status) {
                var doneMsg = "Operation complete with status: " + status;
                alert(doneMsg);
            }
        });
    });

and the action result:

public ActionResult GetMilestones(int? id)
    {             
        var forProject = db.Projects.Where(x => x.ID == id).SingleOrDefault();
        return PartialView("_GetMilestones",forProject);
    }

Or same action result but the ajax request slightly dirrent:

$('#btnGetMilestones').click(function () { 
  var id;
   id = @Model.ID;

    $.ajax({
        url: '/Projects/GetMilestones',
        type: "GET",
        data: "id="+id,
        success: function (data) {
            $('#milestonesContainer').html(data);
        },
        error: function (xhr, status, error) {
            var msg = "Response failed with status: " + status + "</br>"
            + " Error: " + error;
            $('#milestonesContainer').html(msg);
        },
        complete: function (xhr, status) {
            var doneMsg = "Operation complete with status: " + status;
            alert(doneMsg);
        }
    });
});
Arianit
  • 543
  • 2
  • 8
  • 24