我想撰寫許多接收物件 ID 的 GET 處理程式,
site.com/controller/Action1/1234
site.com/controller/Action2/1234
site.com/controller/Action3/1234
我想撰寫一次從資料庫中獲取復雜物件的代碼:
class ComplexObject
{
public string str1 { get; set; }
public string str2 { get; set; }
}
ComplexObject GetFromId(string id)
{
ComplexObject x = Database.GetById(id);
if (x == null)
{
return Http404();
}
return x;
}
然后直接使用物件:
[Route("/[controller]/[action]/{message}")]
[HttpGet]
public string Action1(ComplexObject message)
{
return message.str1;
}
[Route("/[controller]/[action]/{message}")]
[HttpGet]
public string Action2(ComplexObject message)
{
return message.str1;
}
[Route("/[controller]/[action]/{message}")]
[HttpGet]
public string Action3(ComplexObject message)
{
return message.str1;
}
而且我所有的處理程式都只會獲取物件,而不必檢查 ID 是否正確等。
這怎么可能?
uj5u.com熱心網友回復:
在微軟官方檔案描述究竟如何,你可以使用自定義的模型系結資料庫系結路由引數到一個復雜的物件。
這是他們的示例模型系結器:
public class AuthorEntityBinder : IModelBinder
{
private readonly AuthorContext _context;
public AuthorEntityBinder(AuthorContext context)
{
_context = context;
}
public Task BindModelAsync(ModelBindingContext bindingContext)
{
if (bindingContext == null)
{
throw new ArgumentNullException(nameof(bindingContext));
}
var modelName = bindingContext.ModelName;
// Try to fetch the value of the argument by name
var valueProviderResult = bindingContext.ValueProvider.GetValue(modelName);
if (valueProviderResult == ValueProviderResult.None)
{
return Task.CompletedTask;
}
bindingContext.ModelState.SetModelValue(modelName, valueProviderResult);
var value = valueProviderResult.FirstValue;
// Check if the argument value is null or empty
if (string.IsNullOrEmpty(value))
{
return Task.CompletedTask;
}
if (!int.TryParse(value, out var id))
{
// Non-integer arguments result in model state errors
bindingContext.ModelState.TryAddModelError(
modelName, "Author Id must be an integer.");
return Task.CompletedTask;
}
// Model will be null if not found, including for
// out of range id values (0, -3, etc.)
var model = _context.Authors.Find(id);
bindingContext.Result = ModelBindingResult.Success(model);
return Task.CompletedTask;
}
}
然后有多種方法可以使用這種新的模型系結器。一種是在模型本身上添加一個屬性:
[ModelBinder(BinderType = typeof(AuthorEntityBinder))]
public class Author
{
// snip
}
另一種方法是在動作引數上使用一個屬性:
[HttpGet("{id}")]
public IActionResult GetById([ModelBinder(Name = "id")] Author author)
{
// snip
}
uj5u.com熱心網友回復:
我不確定為什么要按照您的建議去做,但它不必要地使事情變得過于復雜并導致對模型系結器的依賴。
這是我將如何實作這一點:
有一個管理復雜物件并將其隱藏在介面后面的類,將其注入控制器:
public interface IComplexObjectManager
{
ComplexObject GetFromId(string id);
}
public class ComplexObjectManager : IComplexObjectManager
{
private readonly Database _database;
public ComplexObjectManager(Database database)
{
_database = database;
}
public ComplexObject GetFromId(string id)
{
ComplexObject x = _database.GetById(id);
return x;
}
}
[ApiController]
public class ComplexObjectController
{
public ComplexObjectController(IComplexObjectManager complexObjectManager)
{
ObjectManager = complexObjectManager;
}
public IComplexObjectManager ObjectManager { get; }
}
然后在您的方法中使用它,將回傳型別更改為操作結果:
[Route("/[controller]/[action]/{id}")]
[HttpGet]
public IActionResult Action1(string id)
{
var obj = ObjectManager.GetFromId(id);
if(obj != null)
return Ok(obj.str1);
else
return NotFound();
}
確保相應地處理回應。
這種方法將事物解耦(可以為 增加進一步的抽象Database),并允許注入和單元測驗。
請檢查代碼的一致性。我很著急地寫了這個。
uj5u.com熱心網友回復:
我沒有做你所要求的事情,但我認為它可以幫助你。首先,我使用BaseController它是因為您可以在執行之前過濾所有操作。
public class BaseController : Controller
{
#region /*IoC*/
public BaseViewModel baseViewModel;
public IUnitOfWork<Product> unitOfWorkProductForCart;
#endregion
#region /*ctor*/
public BaseController(IUnitOfWork<Product> unitOfWorkProductForCart)
{
this.unitOfWorkProduct = unitOfWorkProduct;
}
#endregion
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
string controllerName = filterContext.ActionDescriptor.RouteValues["controller"];
string actionName = filterContext.ActionDescriptor.RouteValues["action"];
if (actionName == "ProductDetails")
{
var urlParameters = filterContext.ActionArguments;
if (urlParameters.Count != 0)
{
var isThatSlug = urlParameters.ElementAt(0).Key;
if (isThatSlug == "slug")
{
var slugCondition = urlParameters.ElementAt(0).Value;
var isThatProductExist = unitOfWorkProduct.RepositoryProduct.GetProductBySlugForChecking(slugCondition.ToString());
if (isThatProductExist.Count == 0)
{
filterContext.Result = new RedirectToRouteResult(new RouteValueDictionary
{
{"controller","Account"},
{"action","NotFound"}
});
}
}
}
}
}
}
在那個例子中,我正在控制引數。如果它是我不想要的東西,它會將您重定向到該NotFound頁面。我希望它能給你一個想法
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/337217.html
