开发者

Backbone.js REST URL with ASP.NET MVC 3

I have been looking into Backbone.js lately and i am now trying to hook it up with my server-side asp.net mvc 3.

This is when i discovered a issue. ASP.NET listens to different Actions, Ex: POST /Users/Create and not just POST /users/. Because of that, the Model.Save() method in backbone.js wil开发者_StackOverflow社区l not work.

How should we tackle this problem? Do i have to rewrite the Backbone.Sync?


The answer is not to override Backbone.sync. You rarely would want to do this. Instead, you need only take advantage of the model's url property where you can assign a function which returns the url you want. For instance,

Forum = Backbone.Model.extend({

  url: function() {
    return this.isNew() ? '/Users/Create' : '/Users/' + this.get('id');
  }

});

where the url used for a model varies based upon whether the model is new. If I read your question correctly, this is all you need to do.


You either have to tell ASP.NET MVC to route proper REST urls or fix Backbone.sync so it sends the GET/POST requests at the proper URLs.

Backbone works with REST not with RESTful URLs. There may be an OS implementation of Backbone.sync that matches your urls though.

Recommend URLs that play more nicely with Backbone:

GET     /forums              ->  index
GET     /forums/new          ->  new
POST    /forums              ->  create
GET     /forums/:forum       ->  show
GET     /forums/:forum/edit  ->  edit
PUT     /forums/:forum       ->  update
DELETE  /forums/:forum       ->  destroy


I wrote a blog post recently describing how to bind .NET MVC to the default Backbone service layer.

Like previous posters have mentioned, there are a number of approaches you could take. I prefer this approach because it requires little configuration.

The controller:

public class ZocController : Controller
{
    public ActionResult Docs()
    {
        return Json(GetDocs(), JsonRequestBehavior.AllowGet);
    }

    [ActionName("Docs")]
    [HttpPost]
    public ActionResult HandlePostDoc(Doctor doc)
    {
        doc.id = Guid.NewGuid();

        CreateDoc(doc);

        return Json(doc);
    }

    [ActionName("Docs")]
    [HttpPut]
    public ActionResult HandlePutDoc(Doctor doc)
    {
        UpdateDoc(doc);

        return new EmptyResult();
    }

    [ActionName("Docs")]
    [HttpDelete]
    public ActionResult HandleDeleteDoc(Guid id)
    {
        DeleteDoc(id);

        return new EmptyResult();
    }
}

The Backbone

window.Doctor = Backbone.Model;

window.Doctors = Backbone.Collection.extend({

    model: Doctor,

    url: '/zoc/docs'

});


i found the following code in https://github.com/sgentile/BackboneContacts

    /// <reference path="backbone.js" />
ModelBase = Backbone.Model.extend({
    defaults: {
        id: null
    },
    url: function (type) {
        //expecting the following conventions on the server:
        //urlRoot should be the controller : controller/
        //create → POST   /action
        //read → GET   /action[/id]
        //update → PUT   /action/id
        //delete → DELETE   /action/id
        var fqUrl = this.urlRoot;
        switch (type) {
            case "POST":
                fqUrl += "create";
                break;
            case "PUT":
                fqUrl += "update";
                break;
            case "DELETE":
                fqUrl += "delete/" + this.get('id');
                break;
            case "GET":
                fqUrl += "read/" + this.get('id');
                break;
        }
        return fqUrl;
    }
});

var methodMap = {
    'create': 'POST',
    'update': 'PUT',
    'delete': 'DELETE',
    'read': 'GET'
};

// Helper function to get a URL from a Model or Collection as a property
// or as a function.
var getUrl = function (object) {
    if (!(object && object.url)) return null;
    return _.isFunction(object.url) ? object.url() : object.url;
};

// Throw an error when a URL is needed, and none is supplied.
var urlError = function () {
    throw new Error('A "url" property or function must be specified');
};

Backbone.sync = function (method, model, options) {
    var type = methodMap[method];

    options.url = _.isString(this.url) ? this.url : this.url(type);

    // Default JSON-request options.
    var params = _.extend({
        type: type,
        dataType: 'json'
    }, options);

    // Ensure that we have a URL.
    if (!params.url) {
        params.url = getUrl(model) || urlError();
    }

    // Ensure that we have the appropriate request data.
    if (!params.data && model && (method == 'create' || method == 'update')) {
        params.contentType = 'application/json';
        params.data = JSON.stringify(model.toJSON());
    }

    // For older servers, emulate JSON by encoding the request into an HTML-form.
    if (Backbone.emulateJSON) {
        params.contentType = 'application/x-www-form-urlencoded';
        params.data = params.data ? { model: params.data} : {};
    }

    // For older servers, emulate HTTP by mimicking the HTTP method with `_method`
    // And an `X-HTTP-Method-Override` header.
    if (Backbone.emulateHTTP) {
        if (type === 'PUT' || type === 'DELETE') {
            if (Backbone.emulateJSON) params.data._method = type;
            params.type = 'POST';
            params.beforeSend = function (xhr) {
                xhr.setRequestHeader('X-HTTP-Method-Override', type);
            };
        }
    }

    // Don't process data on a non-GET request.
    if (params.type !== 'GET' && !Backbone.emulateJSON) {
        params.processData = false;
    }

    // Make the request.
    return $.ajax(params);
};
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜