Asp.net mvc 3 带有ASP.NET MVC 3的Backbone.js REST URL

Asp.net mvc 3 带有ASP.NET MVC 3的Backbone.js REST URL,asp.net-mvc-3,rest,backbone.js,Asp.net Mvc 3,Rest,Backbone.js,我最近一直在研究,现在我正试图将它与我的服务器端asp.net mvc 3连接起来 这就是我发现问题的时候。ASP.NET侦听不同的操作,例如:POST/Users/Create,而不仅仅是POST/Users/。因此,backbone.js中的Model.Save()方法将无法工作 我们应该如何解决这个问题?我必须重写主干网.Sync吗?你要么告诉ASP.NET MVC路由正确的REST URL,要么修复主干网.Sync,以便它在正确的URL发送GET/POST请求 主干网使用REST而不是R

我最近一直在研究,现在我正试图将它与我的服务器端asp.net mvc 3连接起来

这就是我发现问题的时候。ASP.NET侦听不同的操作,例如:
POST/Users/Create
,而不仅仅是
POST/Users/
。因此,backbone.js中的
Model.Save()
方法将无法工作


我们应该如何解决这个问题?我必须重写主干网.Sync吗?

你要么告诉ASP.NET MVC路由正确的REST URL,要么修复主干网.Sync,以便它在正确的URL发送GET/POST请求

主干网使用REST而不是RESTful URL。不过,可能存在与URL匹配的Backbone.sync的操作系统实现

推荐更适合主干网的URL:

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

答案是不要覆盖Backbone.sync。你很少会想这样做。相反,您只需要利用模型的url属性,在该属性中可以分配一个返回所需url的函数。比如说,

Forum = Backbone.Model.extend({

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

});
其中,用于模型的url根据模型是否为新的而变化。如果我没看错你的问题,这就是你所需要做的

我最近写了一篇文章,描述了如何将.NET MVC绑定到默认主干服务层

正如前面的海报所提到的,你可以采取很多方法。我更喜欢这种方法,因为它只需要很少的配置

控制员: 骨干
我在中找到了以下代码

//
ModelBase=Backbone.Model.extend({
默认值:{
id:null
},
url:函数(类型){
//服务器上应具有以下约定:
//urlRoot应该是控制器:controller/
//创造→ 员额/行动
//阅读→ 获取/操作[/id]
//更新→ PUT/action/id
//删除→ 删除/action/id
var fqUrl=this.urlRoot;
开关(类型){
案例“职位”:
fqUrl+=“创建”;
打破
案例“付诸表决”:
fqUrl+=“更新”;
打破
案例“删除”:
fqUrl+=“delete/”+this.get('id');
打破
案例“GET”:
fqUrl+=“read/”+this.get('id');
打破
}
返回fqUrl;
}
});
var methodMap={
“创建”:“发布”,
'update':'PUT',
'删除':'删除',
“读取”:“获取”
};
//Helper函数从模型或集合中获取URL作为属性
//或者作为一种功能。
var getUrl=函数(对象){
if(!(object&&object.url))返回null;
返回u.isFunction(object.url)?object.url():object.url;
};
//当需要URL但未提供URL时引发错误。
var urlError=函数(){
抛出新错误(“必须指定“url”属性或函数”);
};
Backbone.sync=函数(方法、模型、选项){
var type=methodMap[method];
options.url=\ uu.isString(this.url)?this.url:this.url(type);
//默认JSON请求选项。
变量参数=389;.extend({
类型:类型,
数据类型:“json”
},选项);
//确保我们有一个URL。
如果(!params.url){
params.url=getUrl(模型)| | urlError();
}
//确保我们拥有适当的请求数据。
如果(!params.data&&model&&(method='create'| | method==''update')){
params.contentType='application/json';
params.data=JSON.stringify(model.toJSON());
}
//对于较旧的服务器,通过将请求编码为HTML表单来模拟JSON。
if(主干网仿真EJSON){
params.contentType='application/x-www-form-urlencoded';
params.data=params.data?{model:params.data}:{};
}
//对于较旧的服务器,通过使用`\u方法模拟HTTP方法来模拟HTTP`
//和“X-HTTP-Method-Override”头。
if(主干网仿真EHTTP){
如果(类型=='PUT'| |类型=='DELETE'){
if(Backbone.emulateJSON)params.data.\u method=type;
params.type='POST';
params.beforeSend=函数(xhr){
setRequestHeader('X-HTTP-Method-Override',类型);
};
}
}
//不要处理非GET请求上的数据。
if(params.type!=“GET”&&&!Backbone.emulateJSON){
params.processData=false;
}
//提出请求。
返回$.ajax(参数);
};

我一直认为ASP.NET MVC对RESTful URL的实现非常可靠?有人以前做过这件事吗?我应该怎么做,改变主干网同步还是MVC路由?@Anders这是你必须做出的选择。取决于你想要什么网址。(更新答案)。@Anders Raynos是对的。。。“标准”REST是使用映射到对象/名词的路由,让您的“操作”通过用于访问它们的HTTP谓词隐式应用<代码>/users/create则不是REST。。。它试图是“REST-like”或“RESTful”,但不是因为
POST
是唯一适用的动词。GET被用来获取一个表单来创建一个用户,而不是获取一个用户对象,PUT和DELETE没有任何意义。创建一个可以使用的RESTAPI,并按照预期的方式使用主干网。这是重写服务器端内容的一个很好的替代方案。谢谢这仍然有点像是一种黑客/变通方法。雷诺斯在下面有一个更合适的答案。同意。更喜欢兼容的URL,但是,如果您没有控制权,那么上面的方法就是您剩下的。当我回答这个问题时,我意识到了这种僵化。为什么不仅仅是POST/users/?ASP.NETMVC不会阻止你。虽然可以做到这一点,但标准的方法是发布到你所在的同一个url。Som如果我正在创建一个用户,我将打开/user/create。但是正如您所说,如果您也需要的话,这可能会起作用。这在新的MVC4WebAPI中处理得更好。我会建议其他人看看这看起来是一个很好的处理方式!还有人有经验吗
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();
    }
}
window.Doctor = Backbone.Model;

window.Doctors = Backbone.Collection.extend({

    model: Doctor,

    url: '/zoc/docs'

});
    /// <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);
};