接上一次的:【c#/MVC】运用MVC模式,做一个增删查改简单数据库,以及涉及到的知识,本次将部分原本的业务逻辑层和数据访问层剥离出来,单独作为一个API,挂到IIS上,然后访问。
阅读帮助:
重点内容为红色加粗标记,正文为黑色字体,可以略过的解释用淡蓝色表示,自定名词为粉色。引用部分可以看也可以不看。
_____________________________________________________________________________
目录
1、IIS的正确配置,网站的挂载,挂载时的问题:IIS没有对物理路径的读取访问权限
2、WebAPI的接口返回类型:在调用post等方法时报错:405,方法不被允许。
4、在API发布后,调试时弹出“您正在调试XXX的发布版本。。。。调试体验会降级。。。例如不会命中断点。”
6、JSON保存为字符串后,出现的斜杠问题,以及该如何处理这个斜杠.
第一:推荐使用postman工具(谷歌浏览器直接由对应的插件)
第二:使用NuGet使用大佬的程序包:【WebApiTestClient 】
9、API访问时出现httpput和httpdelete的谓词问题,该如何处理。
11、此请求已被阻止,因为当用在 GET 请求中时,会将敏感信息透漏给第三方网站
——————————————————————————————————————————
前提:数据库设计
这个部分因为在之前的【c#/MVC】运用MVC模式,做一个增删查改简单数据库,以及涉及到的知识中已经写过,没有任何改动,在此不表。
——————————————————————————————————————————
创建一个新WebAPI:
新建项目:
【文件】-【新建】-【项目】-【Visual C#】-【Web】-【ASP.net Web 应用程序服务】-选择【Web API】-右侧【改变身份验证】
注1:这里我们可以看到,在下方的【为以下项添加文件夹和核心引用】中的【MVC】和【web API】已经是默认勾选的,和之前创建MVC项目并不一样。
注2:身份验证这里,一般来说肯定是需要的,要根据用户的类型开放相应的权限,不过本例中就简单的设置为不进行验证,以方便学习。
注3:选择【Web API】时,右侧说明为:用于创建可以访问范围广阔的客户端(可以访问浏览器和移动设备)的RESTful HTTP服务的项目模板。
什么是RESTful风格:
基于Rest构建的API就是RESTful风格。
什么是REST:
(Representational State Transfer):表现层状态转移,一种软件架构风格,不是标准(不一定要遵循)。总结的说就是:用URL定位资源,用HTTP动词(GET,POST,PUT,DELETE)描述操作。
使用RESTful的理由:
一是基于JSP的局限性,使前后端分离逐渐成为互联网公司开发的业界标准使用方式。关于前后端分离:有篇很好的文章。
二是目前Client层(客户端层)的类型越来越多,RESTful可以只通过一套接口为IOS、Web、安卓等提供服务。微博开放平台和微信开放平台都采用了RESTful风格。
设计这个风格的思路:
API地址以名词为主,且用复数。对资源的调用都用HTTP动作来进行。这个部分可以参考:
此时,一个新的API空项目就建立好了。
在控制器(Controler)中右键【新建控制器】-【包含读写操作的Web API 2控制器】
新建的右侧可以看到这个控制器会包含创建、读取、更新、删除、和列出条目的REST操作。
这个控制器我命名为:【Student3APIController】。
重点:在项目中的【App_Start】文件夹中,双击打开路由设置【WebAPIConfig】,将默认路由修改为:
//在routeTemplate处添加一个:{action}
//你也可以自由修改这个路由
config.Routes.MapHttpRoute(
name:"ActionAPI",
routeTemplate: "actionapi/{controller}/{action}/{id}",
defaults: new { id = RouteParameter.Optional }
);
然后在模型(model)中右键新建一个类,取名为【Student】作为模型,这个模型是要根据数据库来设计,代码如下:
public class Student
{
public int id { get; set; }
public string name { get; set; }
public string number { get; set; }
public string sex { get; set; }
public int age { get; set; }
public string course1 { get; set; }
public string course2 { get; set; }
}
回到新建的控制器【Student3APIController】中,可以看到和以前的MVC项目不同,它继承的是【ApiController】,同时已经在其中自动生成了get、get(id)、post、delete、put等增删查改的几个操作。
从之前的MVC项目中将有关代码拷贝回来,进行略微的修改,其中涉及到的几个问题将在下面详述:
using部分:
using system.net;
using system.web.http;
using system.net.http;
删除using system.web.mvc;
注意:system.web.mvc;会与system.web.http;中的方法同名冲突,因此要删去对MVC的引用。
。。。。。。。。。。。。。。。。。。。。。。
API部分:
/// <summary>
/// This Web API use to modify the message from studentDB
/// </summary>
public class Student3APIController : ApiController
{
private SqlCommandHelper sqlCommandHelper = new SqlCommandHelper();
private String content=null;
// GET: actionapi/Student3API/GET
/// <summary>
/// Get all records from test database student table.
/// </summary>
/// <returns>Json Array,Convert from .net List.</returns>
[HttpGet]
public JsonResult<List<Student>> Get()
{
string sqlStr = "GetAllUserDetails";
List<Student> students = new List<Models.Student>();
students = sqlCommandHelper.GETStudentMessage(sqlStr, -1);
return Json<List<Student>>(students);
}
/// <summary>
/// Get a records from test database student table due to ID
/// </summary>
/// <param name="id">Student ID</param>
/// <returns>Json Array,Convert from .net List.</returns>
// GET: actionapi/Student3API/GET/1
[HttpGet]
public JsonResult<List<Models.Student>> Get(String id)
{
string sqlStr = "AH_GetUserDetail";
List<Models.Student> students = new List<Models.Student>();
students = sqlCommandHelper.GETStudentMessage(sqlStr, Convert.ToInt16(id));
return Json<List<Models.Student>>(students);
}
// POST: actionapi/Student3API/POST/[para]
/// <summary>
/// Add a student records.
/// </summary>
/// <param name="obj"> dynamic obj,include a student model{name、number、sex、age、course1、course2},post type is [string](age should is int)</param>
/// <returns></returns>
[HttpPost]
public bool Post([FromBody]dynamic obj)
{
//Student student = JsonConvert.DeserializeObject(obj);
string sqlStr = "AddStudentDetails";
SqlParameter[] para =
{
new SqlParameter("@name",SqlDbType.VarChar),
new SqlParameter("@number",SqlDbType.VarChar),
new SqlParameter("@sex",SqlDbType.VarChar),
new SqlParameter("@age",SqlDbType.VarChar),
new SqlParameter("@course1",SqlDbType.NVarChar),
new SqlParameter("@course2",SqlDbType.NVarChar)
};
para[0].Value = obj.name;
para[1].Value = obj.number;
para[2].Value = obj.sex;
para[3].Value = Convert.ToInt16(obj.age);
para[4].Value = obj.course1;
para[5].Value = obj.course2;
//需要为空的参数可以赋值为DBNull.Value
//If need null para value,you can assign it is [DBNull.Value].
bool judgeWriteStudentMessage = sqlCommandHelper.WriteStudentMessage(sqlStr, para);
return judgeWriteStudentMessage;
}
/// <summary>
/// 测试,没有用处。
/// </summary>
/// <param name="test"></param>
/// <returns></returns>
public bool Post2([FromBody]dynamic test)
{
bool judge = false;
if (test.name != "q") judge = true;
return judge;
}
// PUT: actionapi/Student3API/PUT/5
/// <summary>
/// Use to modify student message
/// </summary>
/// <param name="obj">dynamic obj,include a student model{id,name,number,sex,age,course1,course2},post type is [string](age should is int,ID should be exist)</param>
[HttpPost]
public bool Put( [FromBody]dynamic obj)
{
string sqlStr = "ModifyStudentDetails_Id";
SqlParameter[] para =
{
new SqlParameter("@t_id",SqlDbType.Int),
new SqlParameter("@t_name",SqlDbType.VarChar),
new SqlParameter("@t_number",SqlDbType.VarChar)