GVKun编程网logo

如何将错误呈现给客户端?AngularJS / WebApi模型状态(错误怎么描述)

10

对于想了解如何将错误呈现给客户端?AngularJS/WebApi模型状态的读者,本文将是一篇不可错过的文章,我们将详细介绍错误怎么描述,并且为您提供关于AngularJs-.netMVCWebApi

对于想了解如何将错误呈现给客户端?AngularJS / WebApi模型状态的读者,本文将是一篇不可错过的文章,我们将详细介绍错误怎么描述,并且为您提供关于AngularJs -.net MVC WebApi身份验证示例、angularjs – Angular JS MVC Web API模型/参数不绑定.NET Core、angularjs – Angular POST to Web API不传递数据、angularjs – Angular2到REST WebApi CORS问题的有价值信息。

本文目录一览:

如何将错误呈现给客户端?AngularJS / WebApi模型状态(错误怎么描述)

如何将错误呈现给客户端?AngularJS / WebApi模型状态(错误怎么描述)

我正在使用WebApi为后端构建AngularJS
SPA应用程序。我在服务器上使用属性进行模型验证,如果验证失败,这就是我从ModelState返回的内容。

     {"Message":"The request is invalid.","ModelState":{"model.LastName":["Last Name must be at least 2 characters long."]}}

然后如何使用AngularJS将其呈现给客户端?

      //Save User Info    $scope.processDriverForm = function(isValid) {        if (isValid) {            //set button disabled, icon, text            $scope.locked = true;            $scope.icon = ''fa fa-spinner fa-spin'';            $scope.buttonText = ''Saving...'';            $scope.submitted = true;            $scope.formData.birthDate = $scope.formData.birthMonth + ''/'' + $scope.formData.birthDay + ''/'' + $scope.formData.birthYear;            $http({                    method: ''POST'',                    url: ''api/Account/Register'',                    data: $.param($scope.formData),                    headers: { ''Content-Type'': ''application/x-www-form-urlencoded'' } // set the headers so angular passing info as form data (not request payload)                })                .success(function (data) {                    console.log(data);                    toastr.success(''User '' + $scope.formData.username + '' created!'');                    $scope.userForm.$setPristine();                    $scope.formData = {};                    //reset the button                    $scope.locked = false;                    $scope.icon = '''';                    $scope.buttonText = ''Save'';                    //reset validation submitted                    $scope.submitted = false;                })                .error(function (data, response) {                    console.log(data);                    toastr.error(''Ooops! There was an error creating the user. Try again and if the problem persists, contact Support.'');                    //reset the button                    $scope.locked = false;                    $scope.icon = '''';                    $scope.buttonText = ''Save'';                    $scope.submitted = false;                    var resp = {};                    var errors = [];                    for (var key in resp.ModelState) {                        for (var i = 0; i < resp.ModelState[key].length; i++) {                            errors.push(resp.ModelState[key][i]);                        }                    }                    $scope.errors = errors;                });        }        else {            toastr.warning(''Invalid User Form, correct errors and try again.'');        }    };

答案1

小编典典

呼叫服务器时,请根据对$http诺言的拒绝捕获错误。

然后在您的控制器中,我建议在处理显示的错误时将对错误数组的响应展平,如下面的小提琴示例所示:

for (var key in resp.ModelState) {    for (var i = 0; i < resp.ModelState[key].length; i++) {        errors.push(resp.ModelState[key][i]);    }}

放在一起:

// Post the data to the web api/service$http.post(url, data)    .success(successHandler)    .error(function (response) {        // when there''s an error, parse the error        // and set it to the scope (for binding)        $scope.errors = parseErrors(response);    });//separate method for parsing errors into a single flat arrayfunction parseErrors(response) {    var errors = [];    for (var key in response.ModelState) {        for (var i = 0; i < response.ModelState[key].length; i++) {            errors.push(response.ModelState[key][i]);        }    }    return errors;}

AngularJs -.net MVC WebApi身份验证示例

AngularJs -.net MVC WebApi身份验证示例

我有一个.Net MVC WebApi应用程序,并尝试在 Angularjs中专门编写前端.我能够通过json获取数据并对其进行操作,但我现在需要保护数据并将Base64身份验证添加到服务器的标头中.当我浏览一些我的.net视图测试页面时,我得到了相应的登录框,询问用户/通行证,以便我可以继续获取json.

我不知道该怎么做是在我的$资源中设置角度的标题中传递此信息(用户/通行证).有没有完整的例子可以更好地告诉我如何做到这一点?我知道它涉及cookie并使用服务器传回的令牌,但我不知道如何将各个部分放在一起.

当我把所有这些结合在一起时,我希望通过所有层(DAL,RESTFUL,控制台测试层)发布一个完整的骨架示例.

所以问题是 – 在使用AngularJS $资源时,如何将身份验证信息插入客户端的标头中?

谢谢

如果你在服务器端的头部放一个cookie,AngularJS将一直发送这个cookie.你无事可做.

如果你想在Header中传递令牌而不是在Angular端的cxookie中传递令牌,请执行以下操作:$httpProvider.defaults.headers.common [‘X-Auth’] = yourKey;在您的配置块中.

然后,如果您想知道用户是否已登录,或者他是否拥有权限,则只需实现拦截器.这是一个简单的工厂,你会在你的配置块中推送响应者.

该工厂将监听来自服务器的每个响应,并且在他的实现中,您将检查错误情况下响应的状态代码:

401 – >没有记录
403 – >没有授权

工厂的例子:

myModule.factory('myHttpInterceptor',function ($q) {
    return function (promise) {
        return promise.then(function (response) {
            // do something on success              
            return response;
        },function (response) {
            // do something on error
            //check status 401 or 403
            return $q.reject(response);
        });
    };
});

然后把你的工厂放在你的con fig块中的http responseIntercetors中:

myModule.config(function ($httpProvider) {
    $httpProvider.responseInterceptors.push('myHttpInterceptor');
});

请记住,AngularJS 1.1.4中不推荐使用此解决方案(仍然不稳定)……

工厂必须有所不同,请参阅这篇文章了解更多信息:AngularJS Intercept all $http JSON responses

希望能帮助到你

angularjs – Angular JS MVC Web API模型/参数不绑定.NET Core

angularjs – Angular JS MVC Web API模型/参数不绑定.NET Core

我正在使用带有TypeScript和ASP.NET Core MVC / API的Angular JS.

我有一个apiService来处理对服务器的所有POST和GET请求,如下所示:

module TBApp {

    export class apiService {

        static $inject = ['$http','notificationService'];

        constructor(private $http,private notificationService: notificationService) {

        }

        get(url,config,success,failure) {

            return this.$http.get(url,config)

                .then(result => { this.handleResponse(result,success); },result => { this.handleError(result,failure) });
        }

        post(url,data,failure) {

            return this.$http.post(url,data)
                .then(result => { this.handleResponse(result,failure) });
        }

        handleResponse(result,success) {

            alert('success');
            success(result);

        }

        handleError(result,failure) {

            if (result.status === '401') {

                this.notificationService.displayError('Authentication required.');
                //this.$rootScope.prevIoUsstate = this.$location.path();
                //this.$location.path('/login');

            }
            else if (failure !== null) {
                failure(result);
            }
        }
    }
}

现在,当我发送此请求时:

onCompanyChanged(selectedCompany,model,companyName) {

        this.apiService.post('/api/Dashboard/GetAssetListByCompany',{ companyId: selectedCompany.id },response => {

                this.assetListviewmodel = response.data.data;


            },response => {
            this.notificationService.displayError(response.data.message);
        });
    }

它没有绑定控制器中的companyId

这是控制器:

[Route("api/[controller]")]
    public class DashboardController : BaseController
    {
        [HttpPost]
        [Route("GetAssetListByCompany")]
        public IActionResult GetAssetListByCompany([FromBody]int companyId)
        {
            return CreateJsonResult(() =>
            {
                if (companyId == 0) { return new xPTJsonResult(null,xPTStatusCodesEnum.Success,"Company Id is 0"); }

               //var treeModel = _dashboardProvider.GetTreeModelByCompany(companyId,usermodel);

                return new xPTJsonResult(null,"Loaded assets successfully");

            });
        }

}

即使我在浏览器中检查了请求,也表明companyId在Payload中.

enter image description here

NOTE: The same function works when I post a viewmodel

编辑

在上面的场景中,我只将一个参数传递给控制器​​,但在某些情况下,我希望能够在不使用viewmodel的情况下传递2或3个参数.

例如

public IActionResult GetAssetListByCompany([FromBody]int companyId,[FromBody]int assetId)
{....

要么

public IActionResult GetAssetListByCompany([FromBody]int companyId,[FromBody]int assetId,[FromBody]bool canEdit = false)
    {.....

然后在客户端我可以这样做:

this.apiService.post('/api/Dashboard/GetAssetListByCompany',{ companyId: selectedCompany.id,assetId: 123 }.....

要么

this.apiService.post('/api/Dashboard/GetAssetListByCompany',canEdit: true,assetId: 22 }....

解决方法

这里最好的方法是遵循HTTP准则并将操作从POST更改为GET,因为您不修改任何数据.这很简单,仍然可以使用URI通过您的请求发送数据.

MVC改变了

有关各种选项,请参阅Model Binding,此处的最佳方法是基于查询字符串进行绑定,因为您只需要一个基本类型.如果您有一个基本类型数组仍然可以绑定到查询字符串,则查询字符串变量名称将为每个值重复一次.

因此,我们所做的唯一更改是指定参数来自查询字符串,并且它与Http Get请求而不是Post相关联.

[Route("api/[controller]")]
public class DashboardController : BaseController
{
    [HttpGet] // change to HttpGet
    [Route("GetAssetListByCompany")]
    public IActionResult GetAssetListByCompany([FromQuery]int companyId) // use FromQuery
    {
        return CreateJsonResult(() =>
        {
            if (companyId == 0) { return new xPTJsonResult(null,"Company Id is 0"); }

           //var treeModel = _dashboardProvider.GetTreeModelByCompany(companyId,usermodel);

            return new xPTJsonResult(null,"Loaded assets successfully");

        });
    }
}

AngularJS发生了变化

我们扩展apiService以允许使用HttpGet传递调用数据.这可以使用params on the $http call完成,它将使用名称作为查询字符串值名称和值作为值部分,根据传入的数据动态创建URL.

export class apiService {
    /* all other code is left as is,just change the get method to also accept data via the params. If null is passed in then it is ignored. */
    get(url,failure) {
        return this.$http({
            url: url,config: config,params: data,method: "GET"
            })
            .then(result => { this.handleResponse(result,failure) });
    }
}

在通话中我们只需要从post更改为get,它应该可以工作.

// only change from post to get
onCompanyChanged(selectedCompany,companyName) {
    this.apiService.get('/api/Dashboard/GetAssetListByCompany',response => {
            this.assetListviewmodel = response.data.data;
        },response => {
        this.notificationService.displayError(response.data.message);
    });
}

编辑 – 这很灵活

更重要的是,这种设计在角度方面是灵活的.如果您扩展MVC操作或具有采取其他参数的各种操作,则无需执行任何其他更改即可运行.例:

[HttpGet]
[Route("GetSomethingElseFromServer")]
public IActionResult GetSomethingElseFromServer([FromQuery]int companyId,[FromQuery]string assetName,[FromQuery]string companyModelNumber) // use FromQuery

对你的角度api的调用将是

this.apiService.get('/api/Dashboard/GetSomethingElseFromServer',{ companyId: companyId,assetName: somePassedInAssetNameVar,companyModelNumber: somePassedInModelNumber }

编辑 – 您也可以发送数组

要回答关于如何将多个基元类型作为数组发送的问题,您可以这样做.同样,这假设它不是您要发送的复杂类型,但是,例如,公司ID列表.

c#代码

[HttpGet]
[Route("GetAssetListByCompany")]
public IActionResult GetAssetListByCompany([FromQuery]int[] companyIds) // use an array of int ie. int[]. i changed the variable name to make it clear there can be more than 1

Angular调用,注意没有必要更改服务

onCompanyChanged(selectedCompany,{ "companyIds[]": [id1,id2,id3] },// note the name is Now enclosed in quotes,made plural,and includes []. The value is an array
        response => {
            this.assetListviewmodel = response.data.data;
        },response => {
        this.notificationService.displayError(response.data.message);
    });
}

编辑 – 如果你想要POST

您目前只发送一个原始字段,因此POST中的MVC框架无法正确反序列化.您需要将参数包装在视图模型中,将其作为查询字符串部分发送,或将其作为表单字段值发送.这是带有查询字符串部分的POST,它可以正常工作.

选项1

将其附加到URL

[HttpPost] // change to HttpGet
[Route("GetAssetListByCompany")]
public IActionResult GetAssetListByCompany([FromQuery] int companyId) // use FromQuery

角度呼叫

this.apiService.post('/api/Dashboard/GetAssetListByCompany/?companyId=' + selectedCompany.id +,null,// the rest of the code remains unchanged so I did not include it

选项2

扩展apiService以获取params对象,以便它可以构建您的查询.无论哪种方式,你都会遇到调用者不得不对http调用有所了解.

this.apiService.post('/api/Dashboard/GetAssetListByCompany',{companyId: selectedCompany.id},// the rest of the code remains unchanged so I did not include it

post(url,params,failure) {
    return this.$http({
        url: url,data: data,params: params,method: "POST"
        })
        .then(result => { this.handleResponse(result,failure) });
}

选项3

更新视图模型以采用复杂类型,这不需要更改角度代码.

public class ListByCompanyModel {
    public int CompanyId {get;set;}
}

[HttpPost] // change to HttpGet
[Route("GetAssetListByCompany")]
public IActionResult GetAssetListByCompany([FromBody] ListByCompanyModel model) // use FromQuery

angularjs – Angular POST to Web API不传递数据

angularjs – Angular POST to Web API不传递数据

我已经用jQuery编写针对ASP.NET Web API的代码了一段时间,我在Angular中开始了一些新的东西(针对相同的Web API后端编写.)

我正在发布一个方法,该方法将返回系统中实体的一些搜索结果.它看起来像这样:

public IEnumerable<dynamic> Post(string entity,FormDataCollection parameters)
{
    // entity is passed on the route.
    // parameters contains all the stuff I'm trying to get here.
}

如果我使用jQuery.post调用该方法:

$.post('api/search/child',{where : 'ParentID = 1'},function(d){ foo = d });

它运作正常,并返回我期望的.

我在我的角度应用程序中提供了一个类似的调用服务:

$http.post('api/search/child',{ where: 'parentID = ' + parent.ID })
.success(function (data,status,headers,config) {
    // etc.
})

但是当它在服务器上点击我的“Post”方法时,“paramters”为空.

经过一些谷歌搜索后,我尝试添加一个内容类型的标题,以确保它作为JSON传递,并尝试JSON.stringify-ing和$.param() – “数据”参数,但没有做任何事情(和从我所读到的那些不应该是必要的.)我在这里做错了什么?谢谢你的帮助!

更新:
这是来自(工作)jQuery示例的原始请求:

POST http://localhost:51383/api/search/child HTTP/1.1
Accept: */*
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
X-Requested-With: XMLHttpRequest
Referer: http://localhost:51383/mypage.aspx
Accept-Language: en-US
Accept-Encoding: gzip,deflate
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko
Host: localhost:51383
Content-Length: 23
DNT: 1
Connection: Keep-Alive
Pragma: no-cache
Cookie: (etc)
Authorization: (etc)

where=ParentID+%3D+1

来自(失败的)Angular样本的原始请求:

POST http://localhost:51383/api/search/parent HTTP/1.1
Content-Type: application/json;charset=utf-8
Accept: application/json,text/plain,*/*
Referer: http://localhost:51383/mypage.aspx
Accept-Language: en-US
Accept-Encoding: gzip,deflate
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko
Connection: Keep-Alive
Content-Length: 27
DNT: 1
Host: localhost:51383
Pragma: no-cache
Cookie: (etc)

{"where":"scorecardID = 1"}

很奇怪.即使我将’json’数据类型参数添加到jQuery调用的末尾,它仍然会创建www-form-urlencoded请求.那是有效的.我的Web API应用程序已经为JSON设置(但感谢Dalorzo).

解决方法

检查您的配置中是否包含JSON Formatter.它应该是这样的:

System.Web.Http.GlobalConfiguration.Configuration.Formatters.XmlFormatter.SupportedMediaTypes.Clear();
    config.Formatters.Insert(0,new System.Net.Http.Formatting.JsonMediaTypeFormatter());

只有设置了正确的格式化程序,Content-Type = application / json才有效.

您也可以尝试在参数类型旁边使用[FromBody].

angularjs – Angular2到REST WebApi CORS问题

angularjs – Angular2到REST WebApi CORS问题

我正在使用angular2前端和WebApi后端.
webapi启用CORS
var cors = new EnableCorsAttribute("*","*","*");
GlobalConfiguration.Configuration.EnableCors(cors);

它的作品,因为我有不同的网站(jquery / javascript)使用这个api.但是对于角度2,它不会.我收到以下消息:

Response to preflight request doesn’t pass access control check: No ‘Access-Control-Allow-Origin’ header is present on the requested resource.

也许与“预检要求”有关?

谢谢你的帮助.
马科斯

我的Angular2应用程序中有同样的问题.
如已经说明的那样,问题在于,在客户端发出的每个请求都将预检要求发送到服务器之前.

这种请求有一个OPTIONS类型,服务器有责任发送状态为200的预检应答,并设置接收来自该客户端的请求的头文件.

这是我的解决方案(带快递):

// Domain you wish to allow
res.setHeader('Access-Control-Allow-Origin','http://localhost:3000');

// Request methods you wish to allow
res.setHeader('Access-Control-Allow-Methods','GET,POST,PUT,DELETE');

// Request headers you wish to allow
res.setHeader('Access-Control-Allow-Headers','YOUR-CUSTOM-HEADERS-HERE');

// Set to true if you need the website to include cookies in  requests
res.setHeader('Access-Control-Allow-Credentials',true);

// Check if preflight request
if (req.method === 'OPTIONS') {
    res.status(200);
    res.end();
}
else {
    // Pass to next layer of middleware
    next();
}

如您所见,我设置标题,然后如果请求类型为OPTIONS,则提取.在这种情况下,我发回状态200并结束响应.

以这种方式,客户端将被授权,您还可以在所有请求中设置自定义标头.

关于如何将错误呈现给客户端?AngularJS / WebApi模型状态错误怎么描述的介绍已经告一段落,感谢您的耐心阅读,如果想了解更多关于AngularJs -.net MVC WebApi身份验证示例、angularjs – Angular JS MVC Web API模型/参数不绑定.NET Core、angularjs – Angular POST to Web API不传递数据、angularjs – Angular2到REST WebApi CORS问题的相关信息,请在本站寻找。

本文标签: