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!

Community
  • 1
  • 1
Mdb
  • 8,338
  • 22
  • 63
  • 98

1 Answers1

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!

Mdb
  • 8,338
  • 22
  • 63
  • 98