這邊來介紹一下MVC中參數傳遞的方式,主要會透過Model Binder來完成傳遞,Model Binder主要是用於將HTTP request資料對應到controller/Action去。
參數,可以是各種型別,例如string、integer,或是class、list、array也可以。
在.net core MVC架構下Model Binding主要是在startup.cs中設定,之前也有提到,程式碼如下
app.UseMvc(routes =>routes.MapRoute("default", "{controller=Home}/{action=Index}/{id?}"));
簡單傳遞參數
例如,今天的網址為http://www.IronMan.com/Home/Index/999
參數就會如下傳遞
public class HomeController : Controller
{
public IActionResult Index([FromRoute]string id)
{
ViewBag.result = id;
return View();
}
}
接著,我們來使用form傳遞資料到剛剛的controller看看,程式碼如下:
@{
Layout = null;
}
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>Index</title>
</head>
<body>
<h1>Home</h1>
<form action="~/home/index" method="post">
<input type="text" name="id" value="999" />
<input type="submit" value="post" />
</form>
<h3>Result:@ViewBag.result</h3>
</body>
</html>
Model Binder傳遞方式
預設的傳遞方式可能不符合需求,這邊有提供內建的Attribute來指定傳遞方式,主要有下列幾種:
Header:主要是從HTTP Header去Binding,程式碼如下,我們在傳遞參數放上[FromHeader]的attribute
public class HomeController : Controller
{
public IActionResult Index([FromHeader]string test1,[FromHeader] string test2)
{
return View();
}
}
也可以用class接起來,class的property也可以放上FromHeader的attribute
public class Headers
{
[FromHeader]
public string test1 { get; set; }
[FromHeader]
public string test2 { get; set; }
}
複雜資料型別:主要是使用form post,controller的Action會用類別(class)給接起來,而不用一個一個傳遞
Model如下
namespace IronMan.Models
{
public class IronMan
{
[Display(Name = "Id")]
public int Id { get; set; }
[Display(Name = "Name")]
public string Name { get; set; }
[Display(Name = "Birth Date")]
[DataType(DataType.Date)]
public DateTime BirthDate { get; set; }
}
}
View如下,這邊使用tag helper對應資料,其中會指定到對應的Action,Controller沒寫預設導到HomeController
@model IronMan.Models.IronMan
@{
Layout = null;
}
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>AddNew</title>
</head>
<body>
<div class="row">
<div class="col-md-4">
<form asp-action="AddNew">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="Id" class="control-label"></label>
<input asp-for="Id" class="form-control" />
<span asp-validation-for="Id" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Name" class="control-label"></label>
<input asp-for="Name" class="form-control" />
<span asp-validation-for="Name" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="BirthDate" class="control-label"></label>
<input asp-for="BirthDate" class="form-control" />
<span asp-validation-for="BirthDate" class="text-danger"></span>
</div>
<div class="form-group">
<input type="submit" value="AddNew" class="btn btn-default" />
</div>
</form>
</div>
</div>
<pre>@ViewBag.result</pre>
<div>
<a asp-action="Index">Back to List</a>
</div>
</body>
</html>
Controller如下,AddNew action接收前端form post的資料
public class HomeController : Controller
{
public IActionResult Index()
{
return View();
}
[HttpPost]
public IActionResult AddNew(IronMan model)
{
ViewBag.result = $@"
IronMan id : {model.Id}
IronMan Name : {model.Name}
IronMan Birth Date : {model.BirthDate}
";
return View();
}
}
使用class接資料算是MVC架構下常見的方式,也會比一個一個參數傳遞來的好
參考資料
https://docs.microsoft.com/zh-tw/aspnet/core/web-api/advanced/formatting?view=aspnetcore-3.1