MVC 控制器操作返回字符串的替代方案?

Alternatives to MVC Controller Actions returning strings?

我一直在关注使用 Knockout 和 Entity Framework 的 MVC 项目的在线教程。我也在使用存储库模式。

根据我的发现,教程在执行 HTTP POST 请求时返回字符串,如下所示。我担心的是控制器正在返回字符串——它看起来非常简陋,而且我似乎无法找到一个可靠的 sample/tutorial 来说明如何执行这些 POST 请求(同时不返回视图) ),以及捕获数据库异常和 POST 异常。

Javascript:

self.saveNRI = function () {
        var token = $('[name=__RequestVerificationToken]').val();
        var headers = {};
        headers["__RequestVerificationToken"] = token;
        $.ajax({
            type: "POST",
            url: '/nris/Create',
            headers: headers,
            dataType: 'json',
            data: ko.toJSON(self.nri),
            contentType: 'application/json',
            success: function (result) { },
            error: function (err) {
                if (err.responseText == "Success") {
                    window.location.href = '/nris/Index/';
                }
                if (err.responseText == "Failed") {
                    alert("save failed");
                }
            }
        });
    }

控制器:

[HttpPost]
public string Create(DTO incomingModel)
{  
    if (ModelState.IsValid){
        try
        {
            _nriRepository.Insert(incomingModel);                    
        }
        catch (Exception ex)
        {
            return "Failed";
        }         
    }
    return "Success";
}

存储库:

public async void Insert(DTO n)
{
    //Insert code removed for brevity
        await _context.SaveChangesAsync();
}

使用旧的正则 HTTP Status Codes 来传达 API 上的操作结果可能是个好主意®。

创建资源时表示成功的适当代码是 201。通常,响应正文将包含新创建资源的 ID 或 URL。

10.2.2 201 Created

The request has been fulfilled and resulted in a new resource being created. The newly created resource can be referenced by the URI(s) returned in the entity of the response, with the most specific URI for the resource given by a Location header field. The response SHOULD include an entity containing a list of resource characteristics and location(s) from which the user or user agent can choose the one most appropriate. The entity format is specified by the media type given in the Content-Type header field. The origin server MUST create the resource before returning the 201 status code. If the action cannot be carried out immediately, the server SHOULD respond with 202 (Accepted) response instead.

但是,您也可以使用更通用的状态代码 200 来指示成功:

10.2.1 200 OK

The request has succeeded. The information returned with the response is dependent on the method used in the request, for example:

GET an entity corresponding to the requested resource is sent in the response;

HEAD the entity-header fields corresponding to the requested resource are sent in the response without any message-body;

POST an entity describing or containing the result of the action;

TRACE an entity containing the request message as received by the end server.

要传达失败信息,您可能会使用 4xx5xx 范围内的代码。

A 4xx表示故障在客户端。例如,客户端没有发送创建资源所需的所有属性。通用 400 很方便:

10.4.1 400 Bad Request

The request could not be understood by the server due to malformed syntax. The client SHOULD NOT repeat the request without modifications.

然而,5xx 表明您的服务器在完成请求时遇到了问题。

10.5.4 503 Service Unavailable

The server is currently unable to handle the request due to a temporary overloading or maintenance of the server. The implication is that this is a temporary condition which will be alleviated after some delay. If known, the length of the delay MAY be indicated in a Retry-After header. If no Retry-After is given, the client SHOULD handle the response as it would for a 500 response.

在客户端,您可以依靠 jQuery.ajax 根据状态代码适当地路由您的回调。您应该使用更新的基于 Promise 的 API 而不是成功和错误回调。例如:

var jqxhr = $.ajax( "example.php" )
  .done(function() {
    alert( "success" );
  })
  .fail(function() {
    alert( "error" );
  })
  .always(function() {
    alert( "complete" );
  });

来源:http://api.jquery.com/jquery.ajax/

你可以使用优秀的httpstat.us web service to test out response codes. Just append the desired response code to the URL and it will return a mock answer. For example, a success: http://httpstat.us/200

我最喜欢@gadr90 的回答,但我想我还要提到您可以直接从 MVC 中的 ActionResult return JSON。

[HttpPost]
public JsonResult Create(DTO incomingModel)
{  
    if (ModelState.IsValid)
    {
        try
        {
            _nriRepository.Insert(incomingModel);                    
        }
        catch (Exception ex)
        {
            var x = new
            {
                status = "Failed",
                message = ex.Message,
            };
            return this.Json(x);
        }         
    }
    var x = new
    {
        status = "Success",
        message = "",
    };
    return this.Json(x);
}