记录学习成果,以便温故而知新
打算用ASP.net搞个web接口服务,发现建的项目不同,建项目时的选项不一样,差异还是很大的。所以把学习的内容记录一下。
作为对比,本文也把Web应用程序的控制器说明一下。
如图,新建的是“ASP.NET Web应用程序”。C#建的项目不一样,有时差异很明显
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
namespace WebApp.Controllers
{
public class HomeController : Controller
{
public ActionResult Index()
{
return View();
}
public ActionResult About()
{
ViewBag.Message = "Your application description page.";
return View();
}
public ActionResult Contact()
{
ViewBag.Message = "Your contact page.";
return View();
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;
namespace WebApp
{
public class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
}
}
}
为了下面做对比,新增一个MVC控制器UserController,如图
UserController类代码:
public class UserController : Controller
{
// GET: User
public ActionResult Index()
{
return View();
}
// GET: User/Details/5
public ActionResult Details(int id)
{
return View();
}
// GET: User/Create
public ActionResult Create()
{
return View();
}
// POST: User/Create
[HttpPost]
public ActionResult Create(FormCollection collection)
{
try
{
// TODO: Add insert logic here
return RedirectToAction("Index");
}
catch
{
return View();
}
}
// GET: User/Edit/5
public ActionResult Edit(int id)
{
return View();
}
// POST: User/Edit/5
[HttpPost]
public ActionResult Edit(int id, FormCollection collection)
{
try
{
// TODO: Add update logic here
return RedirectToAction("Index");
}
catch
{
return View();
}
}
// GET: User/Delete/5
public ActionResult Delete(int id)
{
return View();
}
// POST: User/Delete/5
[HttpPost]
public ActionResult Delete(int id, FormCollection collection)
{
try
{
// TODO: Add delete logic here
return RedirectToAction("Index");
}
catch
{
return View();
}
}
}
先在Controllers文件下新增Api文件夹。然后如图新增Web API控制器,新增的时候会自动添加“基架”。
生成成功后弹出一个“readme.txt”,内容如下:
Visual Studio 已向项目“WebApp”添加 ASP.NET Web API 2 的 全部集合 个依赖项。
项目中的 Global.asax.cs 文件可能需要其他更改才能启用 ASP.NET Web API。
1. 添加以下命名空间引用:
using System.Web.Http;
using System.Web.Routing;
2. 如果代码尚未定义 Application_Start 方法,请添加以下方法:
protected void Application_Start()
{
}
3. 在 Application_Start 方法的开头添加以下行:
GlobalConfiguration.Configure(WebApiConfig.Register);
当时没有在意这个提示文件,导致后来很曲折,折腾了一阵子才实现了功能。其实这个文件的2、3点已经把问题说的很透彻了!!!
不光是新增了“UserController”控制器,还多出了“WebApiConfig”配置文件
浏览器弹出MVC控制器默认的首页,如图
在浏览器中输入“http://localhost:50910/api/user”访问Web API控制器也能正常响应,如图:
如果访问Web API控制器没有生效,很可能是没有在“Global.asax”文件中“Application_Start()”方法里加入
GlobalConfiguration.Configure(WebApiConfig.Register);
Application_Start防范完整代码
protected void Application_Start()
{
GlobalConfiguration.Configure(WebApiConfig.Register);
AreaRegistration.RegisterAllAreas();
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
}
为了更好的展示效果,在Models中新增Result与User两个类
Result类代码:
public class Result
{
public bool Success { get; set; }
public int ErrorCode { get; set; }
public string ErrorMsg { get; set; }
public static Result Ok(int errorCode = 0, string errorMsg = "操作成功")
{
return new Result { Success = true, ErrorCode = errorCode, ErrorMsg = errorMsg };
}
public static Result Fail(int errorCode = -1, string errorMsg = "操作失败")
{
return new Result { Success = false, ErrorCode = errorCode, ErrorMsg = errorMsg };
}
}
User类代码:
public class User
{
[Display(Name = "ID")]
public long Id { get; set; }
[Display(Name = "用户名")]
[Required(ErrorMessage = "必填")]
[StringLength(20, MinimumLength = 1, ErrorMessage = "{2}到{1}个字符")]
public string Name { get; set; }
[Display(Name = "密码")]
[Required(ErrorMessage = "必填")]
[StringLength(20, MinimumLength = 1, ErrorMessage = "{2}到{1}个字符")]
[DataType(DataType.Password)]
public string Pwd { get; set; }
}
Api目录下UserController类经过华丽改造后的代码:
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web.Http;
using WebApp.Models;
namespace WebApp.Controllers.Api
{
public class UserController : ApiController
{
// GET: api/User
public IEnumerable<User> Get()
{
return new User[] { new User { Id = 1, Name = "Tom", Pwd = "123456" },
new User{ Id = 2, Name = "Jerry", Pwd = "123456" } };
}
// GET: api/User/5
public Result Get(int id)
{
Debug.WriteLine(id);
return Result.Ok();
}
// POST: api/User
public Result Post([FromBody]User user)
{
Debug.WriteLine(user.Id);
Debug.WriteLine(user.Name);
Debug.WriteLine(user.Pwd);
return Result.Ok();
}
// PUT: api/User/5
public Result Put(int id, [FromBody]User user)
{
Debug.WriteLine(id);
Debug.WriteLine(user.Id);
Debug.WriteLine(user.Name);
Debug.WriteLine(user.Pwd);
return Result.Ok();
}
// DELETE: api/User/5
public Result Delete(int id)
{
Debug.WriteLine(id);
return Result.Ok();
}
//特性路由: api/user/show/5
[Route("api/user/show/{id}")]
[HttpGet]
public User Show(int id)
{
Debug.WriteLine(id);
return new User { Id = 5, Name = "Zhang Cuishan", Pwd = "123456" };
}
}
}
MVC控制器继承的是Controller;
WebApi控制器继承的是ApiController
MVC控制器返回视图等
WebApi控制器返回JSON等
MVC控制器通过RouteConfig.cs文件实现
WebApi控制器通过WebApiConfig.cs实现
但是两者都需要在“Global.asax”文件中“Application_Start()”方法执行相应操作生效
Web.config文件中system.webServer如下处理:
<system.webServer>
<handlers>
<remove name="ExtensionlessUrlHandler-Integrated-4.0" />
<remove name="TRACEVerbHandler" />
<add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="*" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
handlers>
<httpProtocol>
<customHeaders>
<add name="Access-Control-Allow-Origin" value="*"/>
<add name="Access-Control-Allow-Headers" value="*"/>
<add name="Access-Control-Allow-Methods" value="*"/>
customHeaders>
httpProtocol>
system.webServer>
HomeController控制器代码:
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using CoreWebApp.Models;
namespace CoreWebApp.Controllers
{
public class HomeController : Controller
{
public IActionResult Index()
{
return View();
}
public IActionResult About()
{
ViewData["Message"] = "Your application description page.";
return View();
}
public IActionResult Contact()
{
ViewData["Message"] = "Your contact page.";
return View();
}
public IActionResult Privacy()
{
return View();
}
[ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
public IActionResult Error()
{
return View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier });
}
}
}
在“Startup.cs”文件中“Configure”方法中
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
namespace CoreWebApp.Controllers
{
public class UserController : Controller
{
// GET: User
public ActionResult Index()
{
return View();
}
// GET: User/Details/5
public ActionResult Details(int id)
{
return View();
}
// GET: User/Create
public ActionResult Create()
{
return View();
}
// POST: User/Create
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create(IFormCollection collection)
{
try
{
// TODO: Add insert logic here
return RedirectToAction(nameof(Index));
}
catch
{
return View();
}
}
// GET: User/Edit/5
public ActionResult Edit(int id)
{
return View();
}
// POST: User/Edit/5
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit(int id, IFormCollection collection)
{
try
{
// TODO: Add update logic here
return RedirectToAction(nameof(Index));
}
catch
{
return View();
}
}
// GET: User/Delete/5
public ActionResult Delete(int id)
{
return View();
}
// POST: User/Delete/5
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Delete(int id, IFormCollection collection)
{
try
{
// TODO: Add delete logic here
return RedirectToAction(nameof(Index));
}
catch
{
return View();
}
}
}
}
先在Controllers文件下新增Api文件夹。然后如图新增Web API控制器,新增的时候会自动添加“基架”。
为了更好的展示效果,在Models中新增Result与User两个类,代码与上面完全相同,就不重复展示。
Api目录下UserController类经过华丽改造后的代码:
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks;
using CoreWebApp.Models;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
namespace CoreWebApp.Controllers.Api
{
[Route("api/[controller]")]
[ApiController]
public class UserController : ControllerBase
{
// GET: api/User
[HttpGet]
public IEnumerable<User> Get()
{
return new User[] { new User { Id = 1, Name = "Tom", Pwd = "123456" },
new User{ Id = 2, Name = "Jerry", Pwd = "123456" } };
}
// GET: api/User/5
[HttpGet("{id}", Name = "Get")]
public Result Get(int id)
{
Debug.WriteLine(id);
return Result.Ok();
}
// POST: api/User
[HttpPost]
public Result Post([FromBody] User user)
{
Debug.WriteLine(user.Id);
Debug.WriteLine(user.Name);
Debug.WriteLine(user.Pwd);
return Result.Ok();
}
// PUT: api/User/5
[HttpPut("{id}")]
public Result Put(int id, [FromBody] User user)
{
Debug.WriteLine(id);
Debug.WriteLine(user.Id);
Debug.WriteLine(user.Name);
Debug.WriteLine(user.Pwd);
return Result.Ok();
}
// DELETE: api/User/5
[HttpDelete("{id}")]
public Result Delete(int id)
{
Debug.WriteLine(id);
return Result.Ok();
}
//api/User/Save
[HttpPost("Save")]
public Result Save([FromBody] User user)
{
Debug.WriteLine(user.Id);
Debug.WriteLine(user.Name);
Debug.WriteLine(user.Pwd);
return Result.Ok();
}
//api/user/show?id=5&name=张翠山
[HttpGet("Show")]
public Result Show(int id, string name)
{
Debug.WriteLine(id);
Debug.WriteLine(name);
return Result.Ok();
}
}
}
感觉完全是靠代码里的属性标志实现的
感觉差异太大,没有可比性。
Startup.cs文件中ConfigureServices方法新增如下代码:
// 配置跨域处理,允许所有来源
services.AddCors(options => options.AddPolicy("cors",
p => p.AllowAnyOrigin().AllowAnyHeader().AllowAnyMethod().AllowCredentials()));
Startup.cs文件中Configure方法新增如下代码:
// 允许所有跨域,cors是在ConfigureServices方法中配置的跨域策略名称
app.UseCors("cors");