.net6Api返回统一结果+Vue3前端访问

目录

第一种

第二种

第三种

Vue3前端访问 


在我们开发api的时候,需要让接口返回统一的接口,这样容易理解,也容易管理。所以封装返回的统一结果是非常必要的。

下面介绍3种方案。

第一种

建立一个控制器,让所有控制器都继承它

文件总览

1.建立ApiResult.cs

namespace net6ApiResult.Common
{
    public class ApiResult<T>
    {
        /// <summary>
        /// 错误代码
        /// </summary>
        public ApiResultCode Code { get; set; }
        /// <summary>
        /// 错误信息 
        /// </summary>
        public string Message { get; set; }
        /// <summary>
        /// 具体数据
        /// </summary>
        public T Data { get; set; }
    }
}

2.建立ApiResultCode.cs

namespace net6ApiResult.Common
{
    public enum ApiResultCode
    {
        //失败 
        Failed,
        //成功
        Success,
        //数据为空
        Empty,
    }
}

3.建立CommonController.cs

using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using net6ApiResult.Common;

namespace net6ApiResult.Controllers
{

    [ApiController]
    [Route("api/[controller]/[action]")]
    public class CommonController : ControllerBase
    {
        protected ApiResult<T> GenActionResultGenericEx<T>(T datas, ApiResultCode code = ApiResultCode.Success, string message = "", Exception ex = null)
        {
            if (ex != null)
            {
                code = ApiResultCode.Failed;
                message = string.IsNullOrWhiteSpace(message) ? ex.Message : $"{message}\n{ex.Message}";
#if Debug
                                message = string.IsNullOrWhiteSpace(message) ? ex.Message : $"{message}\n{ex.Message}";
#endif
            }
            else if (datas == null)


            {
                code = ApiResultCode.Empty;
                message = "数据为空";
            }
            var result = new ApiResult<T>
            {
                Code = code,
                Message = message,
                Data = datas
            };
            return result;
        }
    }
}

4.WeatherForecastController.cs中使用

using Microsoft.AspNetCore.Mvc;
using net6ApiResult.Common;

namespace net6ApiResult.Controllers
{
    [ApiController]
    [Route("api/[controller]/[action]")]
    public class WeatherForecastController : CommonController
    {
        private static readonly string[] Summaries = new[]
        {
        "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
        };

        private readonly ILogger<WeatherForecastController> _logger;

        public WeatherForecastController(ILogger<WeatherForecastController> logger)
        {
            _logger = logger;
        }

        [HttpGet]
        public IEnumerable<WeatherForecast> Get()
        {
            return Enumerable.Range(1, 5).Select(index => new WeatherForecast
            {
                Date = DateTime.Now.AddDays(index),
                TemperatureC = Random.Shared.Next(-20, 55),
                Summary = Summaries[Random.Shared.Next(Summaries.Length)]
            })
            .ToArray();
        }

        [HttpGet]
        public ApiResult<IEnumerable<WeatherForecast>> Get111()
        {
            return GenActionResultGenericEx(Enumerable.Range(1, 5).Select(index => new WeatherForecast
            {
                Date = DateTime.Now.AddDays(index),
                TemperatureC = Random.Shared.Next(-20, 55),
                Summary = Summaries[Random.Shared.Next(Summaries.Length)]
            })
            );
        }

        [HttpGet]
        public ApiResult<string> GetA()
        {
            //可以根据业务进行判断,然后赋值,再返回
            return GenActionResultGenericEx("123", ApiResultCode.Success, "成功");
        }
    }
}

5.效果

  

第二种

使用dynamic动态增加

只需要修改返回的地方

1.WeatherForecastController.cs代码

using Microsoft.AspNetCore.Mvc;
//using net6ApiResult.Common;
using Newtonsoft.Json;

namespace net6ApiResult.Controllers
{
    [ApiController]
    [Route("api/[controller]/[action]")]
    public class WeatherForecastController : ControllerBase
    {
        private static readonly string[] Summaries = new[]
        {
        "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
        };

        private readonly ILogger<WeatherForecastController> _logger;

        public WeatherForecastController(ILogger<WeatherForecastController> logger)
        {
            _logger = logger;
        }

        [HttpGet]
        public IEnumerable<WeatherForecast> Get()
        {
            return Enumerable.Range(1, 5).Select(index => new WeatherForecast
            {
                Date = DateTime.Now.AddDays(index),
                TemperatureC = Random.Shared.Next(-20, 55),
                Summary = Summaries[Random.Shared.Next(Summaries.Length)]
            })
            .ToArray();
        }

        [HttpGet]
        public object Get111()
        {
            dynamic retObject;        //使用object retObject;也可以,最好使用dynamic

            var retdata = Enumerable.Range(1, 5).Select(index => new WeatherForecast
            {
                Date = DateTime.Now.AddDays(index),
                TemperatureC = Random.Shared.Next(-20, 55),
                Summary = Summaries[Random.Shared.Next(Summaries.Length)]
            })
             .ToArray();    //业务数据,可以根据业务进行判断,然后赋值

            //object data1 = JsonConvert.SerializeObject(retdata);   //如果加上会出现转义符
            retObject = new { retcode = "0", retmsg = "成功", data = retdata };
            return retObject;


        }

        [HttpGet]
        public object GetA()
        {
            dynamic retObject;

            var retdata = "123";     //业务数据,可以根据业务进行判断,然后赋值
            retObject = new { retcode = "0", retmsg = "成功", data = retdata };
            //return JsonConvert.SerializeObject(retObject);   //这里不要序列化,如果改成序列化后,接口的值是字符串,一行值。
            return retObject;
        }
    }
}

2.效果

第三种

建立一个类,使用过滤器,继承IResultFilter或者IAsyncResultFilter接口。

1.ApiResult.cs代码

namespace net6ApiResult.Common
{
      public class ApiResult 
    {
        public int Code { get; set; }
        public string? Msg { get; set; }
        public object? Data { get; set; }
    }
}

2.ResultFilter.cs代码

using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.AspNetCore.Mvc;
using System.Net;
using Newtonsoft.Json;
using Microsoft.AspNetCore.SignalR;

namespace net6ApiResult.Common
{
    public class ResultFilter : IResultFilter
    {
        public void OnResultExecuted(ResultExecutedContext context)
        {
            //返回结果之后
        }

        public void OnResultExecuting(ResultExecutingContext context)
        {
            object? data = null;
            if (context.Result is ObjectResult objectResult)
            {
                data = objectResult.Value;
            }

            var result = new ApiResult();
            if (data == null || data.ToString()?.Length == 0)
            {
                result.Code = 0;
                result.Msg = "数据为空";
            }
            else
            {
                result.Code = 1;
                result.Msg = "成功";

            }
            result.Data = data;
            //返回结果之前
            context.Result = new JsonResult(result);

            // 返回状态码设置为200,表示成功
            //StatusCode = (int)HttpStatusCode.OK,
            // 设置返回格式
            //ContentType = "application/json;charset=utf-8",
            //Content = JsonConvert.SerializeObject(result)
        
        }
    }
}

3.使用的时候,不需要调用,自动根据返回结果进行过滤

using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
//using net6ApiResult.Common;
using Newtonsoft.Json;

namespace net6ApiResult.Controllers
{
    [ApiController]
    [Route("api/[controller]/[action]")]
    public class WeatherForecastController : ControllerBase
    {
        private static readonly string[] Summaries = new[]
        {
        "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
        };

        private readonly ILogger<WeatherForecastController> _logger;

        public WeatherForecastController(ILogger<WeatherForecastController> logger)
        {
            _logger = logger;
        }

        [HttpGet]
        public IEnumerable<WeatherForecast> Get()
        {
            return Enumerable.Range(1, 5).Select(index => new WeatherForecast
            {
                Date = DateTime.Now.AddDays(index),
                TemperatureC = Random.Shared.Next(-20, 55),
                Summary = Summaries[Random.Shared.Next(Summaries.Length)]
            })
            .ToArray();
        }

        [HttpGet]

        public object Get111()
        {
            return Enumerable.Range(1, 5).Select(index => new WeatherForecast
            {
                Date = DateTime.Now.AddDays(index),
                TemperatureC = Random.Shared.Next(-20, 55),
                Summary = Summaries[Random.Shared.Next(Summaries.Length)]
            })
           .ToArray();


        }

        [HttpGet]
        public object GetA()
        {

            var retdata = "123";     //业务数据,可以根据业务进行判断,然后赋值

            return retdata;
        }

        [HttpGet]
        public object GetB()
        {

            var retdata = "";     //业务数据,可以根据业务进行判断,然后赋值

            return retdata;
        }
        [HttpGet]
        public object GetC()
        {

            object retdata = null;     //业务数据,可以根据业务进行判断,然后赋值

            return retdata;
        }
    }
}

4.全局注册

using net6ApiResult.Common;

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.

builder.Services.AddControllers();
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
builder.Services.AddControllers(o => o.Filters.Add(typeof(ResultFilter)));  //全局注册
var app = builder.Build();

// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
    app.UseSwagger();
    app.UseSwaggerUI();
}

app.UseHttpsRedirection();

app.UseAuthorization();

app.MapControllers();

app.Run();

5.效果

 

Vue3前端访问 

当我们做好了webapi接口后,然后就需要在前端进行访问了。

1.在axios中,进行响应拦截,把需要的数据传递给前端的页面

import axios from 'axios'



//export将service传出去
export const service = axios.create({
	baseURL: '/api'

})


//下面有2种写法,一种是声明函数的写法,一种是箭头函数的写法,都可以

//request interceptor  请求拦截器
service.interceptors.request.use(
	function(config) {

		return config
	},
	function(error) {
		// 对请求错误做些什么

		console.log(error)
		console.log('这里是请求错误')

		return Promise.reject(error)
	}
)


//响应拦截器
service.interceptors.response.use(
	res => {
		// 在请求成功后的数据处理
		if (res.status === 200) {
			console.log(res.status)
			console.log('这里是请求成功后')


			return res.data;//返回需要的数据
		} else {
			console.log(res.status)
			console.log('这里是请求失败后')


			return res;
		}

	},
	err => {
		// 在响应错误的时候的逻辑处理
		console.log('这里是响应错误')

		return Promise.reject(err)
	});

2.同时,前端需要进行接收,就不用判断状态了

<script setup>
	import {
		ref,
		onMounted,
		reactive
	} from 'vue'
	import {
		service
	} from "/store/demoAxios.js"
	// import axios from 'axios'
	let user = ref("admin")
	let passWord = ref("123456")

	const form = reactive({
		params: '',
		pagesize: 2,
		pagenum: 4,
		data: {

		}
	})
	console.log(form)
	const Login = async () => {

		await service.get(`/WeatherForecast/GetA`).then(res => {
			// if (res.status == 200) {
			console.log(1111)
			console.log(res)
			console.log(res.Code)
			console.log(res.Data)
			console.log(res.Message)
			console.log(222)
			//}
		})

		// await service.get(`http://localhost:5000/api/User/Login?userId=1&pwd=1`).then(res => {
		// 			if (res.status == 200) {
		// 				console.log(1111)
		// 				console.log(res.data)
		// 				console.log(222)
		// 			}
		// 		})


	}

	//初始化后执行
	onMounted(() => {
		Login()
	})
</script>

<template>

</template>

<style scoped>
	a {
		color: #42b983;
	}
</style>

3.效果

在前端界面,就能看到对应的值了,这样前后端基本上就统一了返回格式,当然还可以继续优化的更好。

 可结合这个一起看

 VUE3中,使用Axios_故里2130的博客-CSDN博客_vue3中安装axios

拓展:

其中api中,还可以增加异常捕捉

1.在ResultFilter中增加GlobalExceptionFilter

using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.AspNetCore.Mvc;
using System.Net;
using Newtonsoft.Json;
using Microsoft.AspNetCore.SignalR;

namespace net6ApiResult.Common
{
    public class ResultFilter : IResultFilter
    {
        public void OnResultExecuted(ResultExecutedContext context)
        {
            //返回结果之后
        }

        public void OnResultExecuting(ResultExecutingContext context)
        {
            object? data = null;
            if (context.Result is ObjectResult objectResult)
            {
                data = objectResult.Value;
            }

            var result = new ApiResult();
            if (data == null || data.ToString()?.Length == 0)
            {
                result.Code = 0;
                result.Msg = "数据为空";
            }
            else
            {
                result.Code = 1;
                result.Msg = "成功";

            }
            result.Data = data;
            //返回结果之前
            context.Result = new JsonResult(result);

            // 返回状态码设置为200,表示成功
            //StatusCode = (int)HttpStatusCode.OK,
             设置返回格式
            //ContentType = "application/json;charset=utf-8",
            //Content = JsonConvert.SerializeObject(result)
        
        }
    }

    public class GlobalExceptionFilter : IExceptionFilter
    {
        readonly IWebHostEnvironment hostEnvironment;
        readonly ILogger<GlobalExceptionFilter> logger;
        public GlobalExceptionFilter(IWebHostEnvironment _hostEnvironment, ILogger<GlobalExceptionFilter> _logger)
        {
            this.hostEnvironment = _hostEnvironment;
            this.logger = _logger;
        }

        public void OnException(ExceptionContext context)
        {
            if (!context.ExceptionHandled)//如果异常没有处理
            {
                var result = new ApiResult
                {
                    Code = 500,
                    Data = null,
                    Msg = "服务器发生未处理的异常"
                };

                if (hostEnvironment.IsDevelopment()) //开发环境,弹出错误消息和数据
                {
                    result.Msg += "," + context.Exception.Message;
                    result.Data = context.Exception.StackTrace;
                }

                logger.LogError(context.Exception.Message);

                context.Result = new JsonResult(result);
                context.ExceptionHandled = true;//异常已处理
            }
        }
    }

}

2.在控制器中增加异常的方法

    [HttpGet]
        public object GetD()
        {
            throw new NotImplementedException();  //抛出异常
        }

3.在Program中进行注入

builder.Services.AddControllers(option =>
{
    //全局异常过滤器
    option.Filters.Add<GlobalExceptionFilter>();
});

4.效果

运行后,点击方法,会报错,并且弹出固定的返回格式,正常和异常返回格式都统一了。

猜你喜欢

转载自blog.csdn.net/u012563853/article/details/128820307