问题
我有一些看起来像这样的视图组件:
public IViewComponentResult Invoke(BuyerViewModel buyer)
我希望它们能够接受BuyerViewModel
或代表BuyerViewModel
的JSON字符串。例如,当您将JSON从JavaScript传递到控制器方法时,如果该方法期望Dog
类型的参数,则控制器会自动尝试将JSON验证为Dog
实例。我正在尝试模仿这种行为。
目的是这些示例的两个有效:
var buyer = new BuyerSummaryViewModel() { FirstName = "John" };
ViewComponent("Buyer", buyer);
ViewComponent("Buyer", "{"Name":"John Smith"}");
为什么?
我正在尝试制作一种通用的JavaScript方法,该方法可以随时获取视图组件:
const fetchViewComponent = async (viewComponentName, viewModel) => {
let data = { viewComponentName, viewModel };
let html = await $.get(`/Order/FetchViewComponent`, data);
return html;
}
//Get a BuyerViewComponent (example)
(async () => {
let component = await fetchViewComponent("Buyer", `@Html.Raw(Newtonsoft.Json.JsonConvert.SerializeObject(Model.Buyer))`);
console.log(component);
})();
我尝试过的
如果我指定ViewModel是BuyerViewModel
,则可以使用。JSON字符串被自动估算为BuyerViewModel
。
public class FetchViewComponentRequest
{
public string ViewComponentName { get; set; }
public BuyerViewModel ViewModel { get; set; }
// ^^^^^^^^^^^^^^
}
[HttpGet]
public IActionResult FetchViewComponent(FetchViewComponentRequest request)
{
return ViewComponent(request.ViewComponentName, request.ViewModel);
}
问题
但是,我不想指定类型;我希望这是通用。所以我尝试了:
public class FetchViewComponentRequest
{
public string ViewComponentName { get; set; }
public string ViewModel { get; set; }
// ^^^^^^
}
[HttpGet]
public IActionResult FetchViewComponent(FetchViewComponentRequest request)
{
return ViewComponent(request.ViewComponentName, request.ViewModel);
}
,但正如预期的那样,request.ViewModel
不是正确的类型;它在Invoke
方法中结束null
。我希望我可以指定一个标志或更多的全球内容,以便将此字符串隐含地化为预期类型。
有一个更简单的方法来做到这一点?或者,如果没有,我想设想的方式是可能的吗?
(我正在使用 .net Core 2.2 (
也许使您的fetchViewComponentRequest通用?
public class FetchViewComponentRequest<T>
{
public string ViewComponentName { get; set; }
public T ViewModel { get; set; }
// ^^^^^^^^^^^^^^
}
[HttpGet]
public IActionResult FetchViewComponent(FetchViewComponentRequest<BuyerViewModel> request)
{
return ViewComponent(request.ViewComponentName, request.ViewModel);
}
该方法需要了解使对象进入的类型。
public T Convert<T>(dynamic obj) where T:class,new()
{
T myob = null;
if (obj !=null && obj is T)
{
myob = obj as T;
}
else if (obj is string)
{
//convert to type
myob = JsonConvert.DeserializeObject<T>(obj);
}
return myob;
}
好吧,我不确定您需要什么。
,但这是一种动态的方法,而无需指定<T>
。
//Assume that the namespace is DynamicTypeDemo
public class DynamicType {
// eg "DynamicTypeDemo.Cat, DynamicTypeDemo"
public string TypeName { get; set; } // the full path to the type
public string JsonString { get; set; }
}
现在您可以简单的DeserializeObject
public object ToObject(DynamicType dynamicType){
var type = Type.GetType(dynamicType.TypeName);
// Here you could check if the json is list, its really upp to you
// but as an example, i will still add it
if (dynamicType.JsonString.StartsWith("[")) // its a list
type =(List<>).MakeGenericType(type);
return JsonConvert.DeserializeObject(dynamicType.JsonString, type);
}
这就是它的工作方式
var item = new DynamicType(){
TypeName = "DynamicTypeDemo.Cat, DynamicTypeDemo", // or typeof(Cat).AssemblyQualifiedName
JsonString = "{CatName:'Test'}"; // And for a list "[{CatName:'Test'}]"
}
object dynamicObject= ToObject(item); // return it to the javascript
Cat cat = dynamicObject as Cat; // Cast it if you want