问题描述
在使用REST风格的API,我们经常看到的AJAX调用象那个下面我们围绕JavaScript的文件散落现代Web项目。
In modern web-projects that use RESTful API's we often see AJAX-calls like the one below littered around our JavaScript-files.
$.ajax({
type: "POST",
url: myapp.baseUrl + 'Api/Note',
data: ko.mapping.toJSON(note),
contentType: 'application/json',
}).done(function (response) {
// do something
}).fail(function (jqxhr) {
// do something else
});
我爱的WebAPI,我爱淘汰赛,我喜欢绑两者结合起来。然而,这些AJAX的调用是相当冗长,并包含各种我不是真正感兴趣的细节,以便相反,我创建一个围绕这些方法的包装:
I love WebAPI, I love Knockout and I love tying the two together. However these AJAX-calls are quite verbose and contain all kinds of details that I am not really interested in. So instead, I create a wrapper around these methods:
myapp.api.saveNote(note)
然而,这仍然需要我实际编写包含AJAX调用的包装。我想知道,如果你能真正的
ProxyApi产生无效的JavaScript我的解决方案,其中载百余单独的WebAPI的行动。这可能是因为ProxyApi并不包括所有的WebAPI的功能,如自定义的ActionName属性。此外,该ProxyApi库是在笨重的侧合我的口味了一下。必须有这样做更有效的方式...
ProxyApi generated invalid JavaScript for my solution which contained over a hundred separate WebAPI actions. This is probably because ProxyApi does not cover all WebApi features such as custom ActionName attributes. Moreover the ProxyApi library is a bit on the bulky side to my taste. There has to be a more efficient way to do this...
所以我决定去看看在ASP.NET的WebAPI源$ C $ c和原来的WebAPI已自描述的功能内置到它。您可以使用下面的code从任何地方在你的ASP.NET解决方案来访问的WebAPI的元数据:
So I decided to take a look at the ASP.NET WebAPI source code and it turns out WebAPI has self-describing functionality built into it. You can use the following code from anywhere in your ASP.NET solution to access WebAPI metadata:
var apiExplorer = GlobalConfiguration.Configuration.Services.GetApiExplorer();
根据从 apiExplorer.ApiDescriptions
输出
,我滚我自己的元数据提供商:
Based on the output from apiExplorer.ApiDescriptions
, I rolled my own metadata provider:
public class MetadataController : Controller
{
public virtual PartialViewResult WebApiDescription()
{
var apiExplorer = GlobalConfiguration.Configuration.Services.GetApiExplorer();
var apiMethods = apiExplorer.ApiDescriptions.Select(ad => new ApiMethodModel(ad)).ToList();
return PartialView(apiMethods);
}
public class ApiMethodModel
{
public string Method { get; set; }
public string Url { get; set; }
public string ControllerName { get; set; }
public string ActionName { get; set; }
public IEnumerable<ApiParameterModel> Parameters { get; set; }
public ApiMethodModel(ApiDescription apiDescription)
{
Method = apiDescription.HttpMethod.Method;
Url = apiDescription.RelativePath;
ControllerName = apiDescription.ActionDescriptor.ControllerDescriptor.ControllerName;
ActionName = apiDescription.ActionDescriptor.ActionName;
Parameters = apiDescription.ParameterDescriptions.Select(pd => new ApiParameterModel(pd));
}
}
public class ApiParameterModel
{
public string Name { get; set; }
public bool IsUriParameter { get; set; }
public ApiParameterModel(ApiParameterDescription apiParameterDescription)
{
Name = apiParameterDescription.Name;
IsUriParameter = apiParameterDescription.Source == ApiParameterSource.FromUri;
}
}
}
一起使用此控制器以下几种观点:
Use this controller in conjunction with the following view:
@model IEnumerable<Awesome.Controllers.MetadataController.ApiMethodModel>
<script type="text/javascript">
var awesome = awesome || {};
awesome.api = {
metadata: @Html.Raw(Json.Encode(Model))
};
$.each(awesome.api.metadata, function (i, action) {
if (!awesome.api[action.ControllerName]) {
awesome.api[action.ControllerName] = {};
}
awesome.api[action.ControllerName][action.ActionName] = function (parameters) {
var url = '/' + action.Url;
var data;
$.each(action.Parameters, function (j, parameter) {
if (parameters[parameter.Name] === undefined) {
console.log('Missing parameter: ' + parameter.Name + ' for API: ' + action.ControllerName + '/' + action.ActionName);
} else if (parameter.IsUriParameter) {
url = url.replace("{" + parameter.Name + "}", parameters[parameter.Name]);
} else if (data === undefined) {
data = parameters[parameter.Name];
} else {
console.log('Detected multiple body-parameters for API: ' + action.ControllerName + '/' + action.ActionName);
}
});
return $.ajax({
type: action.Method,
url: url,
data: data,
contentType: 'application/json'
});
};
});
</script>
控制器将使用所有可用的WebAPI行动 ApiExplorer
生成的元数据。该视图将呈现此数据为JSON,然后执行一些JavaScript将这些数据转换为实际的可执行的JavaScript函数。
The controller will use the ApiExplorer
to generate metadata about all available WebAPI actions. The view will render this data as JSON and then execute some JavaScript to transform this data to actual executable JavaScript functions.
要使用魔法这一点,请将下面一行在布局网页的头部在您的jQuery的参考。
To use this little bit of magic, insert the following line in the head of your Layout page after your jQuery reference.
@Html.Action(MVC.Metadata.WebApiDescription())
从现在起,你可以让你的WebAPI调用看起来是这样的:
From now on, you can make your WebAPI calls look like this:
// GET: /Api/Notes?id={id}
awesome.api.Notes.Get({ id: id }).done(function () {
// .. do something cool
});
// POST: /Api/Notes
awesome.api.Notes.Post({ form: formData }).done(function () {
// .. do something cool
});
这个简单的代理会自动区分请求体参数查询字符串参数。缺少参数或多个身体参数将产生错误prevent错字的或其他常见的WebAPI开发错误。
This simple proxy will automatically distinguish query string parameters from request body parameters. Missing parameters or multiple body-parameters will generate an error to prevent typo's or other common WebAPI development errors.
这篇关于基础上产生一个ASP.NET的WebAPI控制器一个JS-客户的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!