0

I have an mvc 4 application. I am migrating some of my logic to use web API. I cannot make ChangeState method work in the following code ( 404 file not found). I saw that post:

WebApi adding another Get Method

and I am thinking of making a different controller for states as it is different entity, but I am curious how to make it work for this situation.

public class FranchiseController : ApiController
{
    [DataContext]
    public IEnumerable<FranchiseInfoViewModel> GetAllFranchises()
    {
        var allFranchises = new List<FranchiseInfoViewModel>();
        var franchiseInfoList = _franchiseService.GetAll();

        foreach (var franchiseInfo in franchiseInfoList)
        {
            allFranchises.Add(new FranchiseInfoViewModel(franchiseInfo, p => p.IsImportant));
        }

        return allFranchises;
    }

    [DataContext]
    [System.Web.Http.HttpPost]
    public string ChangeState(int franchiseId, FranchiseProductionStates state)
    {
        _franchiseService.ChangeProductionState(franchiseId, state);

        var redirectToUrl = "List";

        return redirectToUrl;
    }

    [DataContext]
    public FranchiseInfoViewModel GetFranchise(int? franchiseId)
    {
        var realId = franchiseId ?? default(int);
        var franchiseInfo = _franchiseService.CreateOrGet(realId);

        var franchiseInfoViewModel = new FranchiseInfoViewModel(franchiseInfo, p => true);

        return franchiseInfoViewModel;
    }
}

Here are my routes:

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

config.Routes.MapHttpRoute(
    name: "DefaultApiPlusActionAndFolderid",
    routeTemplate: "api/{controller}/{action}/{franchiseId}/{state}",
    defaults: null,
    constraints: new { action = @"[a-zA-Z]+", franchiseId = @"\d+", state = @"[a-zA-Z]+" }
);

and my js code for calling the action method:

var changeState = function (franchiseId, state) {
    var deferred = $.Deferred();
    amplify.request({
        resourceId: 'changeState',
        success: deferred.resolve,
        error: deferred.reject,
        data: { franchiseId: franchiseId, state: state }
    });
    return deferred;
};

amplify.request.define('changeState', 'ajax', {
    url: "/api/franchise/ChangeState",
    type: "POST",
    dataType: 'json',
    decoder: errorsDecoder
});

Note: FranchiseProductionStates is of type enum. Any suggestions are welcome. This is my first experience with web api. Thanks!

1 Answer 1

0

I was able to make this work:

Here is how the action method should look like:

[HttpPut]
public string ChangeState(int id, [FromBody]FranchiseProductionStates state)
{
    _franchiseService.ChangeProductionState(id, state);

    var redirectToUrl = "List";

    return redirectToUrl;
}

Note the added [FromBody] attribute. Also this is in fact a PUT verb, not POST.

This is the route:

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

And this is how the ajax call should be done:

amplify.request.define('changeState', 'ajax', {
                    url: "/api/franchise/ChangeState/3",
                    type: "POST",
                    //dataType: 'json',
                    contentType: 'application/json; charset=utf-8',
                    decoder: errorsDecoder
                });

For simplicity I have hardcoded the id parameter added to the url.

Thanks!

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.