加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

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

发布时间:2020-12-17 06:57:58 所属栏目:安全 来源:网络整理
导读:我正在使用带有TypeScript和ASP.NET Core MVC / API的Angular JS. 我有一个apiService来处理对服务器的所有POST和GET请求,如下所示: module TBApp { export class apiService { static $inject = ['$http','notificationService']; constructor(private $ht
我正在使用带有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

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读