- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我有一个问题要问你们做 Web API REST 服务的人。您如何设计您的服务来处理单个实体的 POST,以及能够接收所述实体集合的 POST?
例如:
public IHttpActionResult Post([FromBody]User value)
{
// stuff
}
public IHttpActionResult Post([FromBody]IEnumerable<User> values)
{
// stuff
}
最佳答案
我最终使用了我最初的第三个和第四个想法的组合。
我正在为此添加我自己的答案,以演示我是如何使其工作的。在我所做的所有谷歌搜索中,我还没有找到一个清晰的例子来说明如何做到这一点。我决定不打一个总是需要 IEnumerable 的调用,而不管要发布一个还是多个。做出这个决定的原因是我考虑的时间越长,我就越意识到插入一个或多个用户所涉及的行为是完全不同的。例如,如果我提交了一个用户并且由于没有填写必填字段而导致验证失败,我希望收到一个错误响应,其中包含服务器拒绝它的原因的详细信息。如果一次提交多个用户,还会这样吗?我需要为每个在发布过程中失败的用户提供错误原因吗?根据我的需求,答案是否定的。这需要以不同的方式处理。
因此,我的答案是在我的 web api 解决方案中将 REST 调用与 RPC(远程过程调用)结合起来。但是,如果沿着这条路走,我的要求是 RPC 调用需要在不同的 Controller 中,但网址仍需要指向相同的整体“ Controller ”(路由的 {controller} 部分,如 api/{controller })。
例如,这个 web api url 接受 REST 动词 Get、Post、Put 和 Delete:
api/User
api/User/import
public class MyHttpControllerSelector : IHttpControllerSelector
{
private const string ActionKey = "action";
private const string ControllerKey = "controller";
private readonly HttpConfiguration _configuration;
private readonly Lazy<Dictionary<string, HttpControllerDescriptor>> _controllers;
public MyHttpControllerSelector(HttpConfiguration config)
{
_configuration = config;
_controllers = new Lazy<Dictionary<string, HttpControllerDescriptor>>(InitializeControllerDictionary);
}
private Dictionary<string, HttpControllerDescriptor> InitializeControllerDictionary()
{
var dictionary = new Dictionary<string, HttpControllerDescriptor>(StringComparer.OrdinalIgnoreCase);
var controllerTypes = GetControllerTypes();
foreach (var type in controllerTypes)
{
var controllerName = type.Name.Remove(type.Name.Length - DefaultHttpControllerSelector.ControllerSuffix.Length);
dictionary[controllerName] = new HttpControllerDescriptor(_configuration, type.Name, type);
}
return dictionary;
}
private IEnumerable<Type> GetControllerTypes()
{
var assembliesResolver = _configuration.Services.GetAssembliesResolver();
var controllersResolver = _configuration.Services.GetHttpControllerTypeResolver();
return controllersResolver.GetControllerTypes(assembliesResolver);
}
private static T GetRouteVariable<T>(IHttpRouteData routeData, string name)
{
object result = null;
if (routeData.Values.TryGetValue(name, out result))
{
return (T)result;
}
return default(T);
}
public HttpControllerDescriptor SelectController(HttpRequestMessage request)
{
var routeData = GetRouteData(request);
var controllerName = GetRequestedControllerName(routeData);
var actionName = GetRequestedActionName(routeData);
var isApiRoute = GetIsApiRoute(routeData);
var controllerSelectorKey = GetControllerSelectorKey(actionName, controllerName, isApiRoute);
return GetControllerDescriptor(request, controllerSelectorKey);
}
private bool GetIsApiRoute(IHttpRouteData routeData)
{
return routeData.Route.RouteTemplate.Contains("api/");
}
private static IHttpRouteData GetRouteData(HttpRequestMessage request)
{
var routeData = request.GetRouteData();
if (routeData == null)
throw new HttpResponseException(HttpStatusCode.NotFound);
return routeData;
}
private HttpControllerDescriptor GetControllerDescriptor(HttpRequestMessage request, string controllerSelectorKey)
{
HttpControllerDescriptor controllerDescriptor = null;
if (!_controllers.Value.TryGetValue(controllerSelectorKey, out controllerDescriptor))
{
throw new HttpResponseException(HttpStatusCode.NotFound);
}
return controllerDescriptor;
}
private static string GetControllerSelectorKey(string actionName, string controllerName, bool isApi)
{
return string.IsNullOrWhiteSpace(actionName) || !isApi
? controllerName
: string.Format("{0}{1}", controllerName, "Rpc");
}
private static string GetRequestedControllerName(IHttpRouteData routeData)
{
string controllerName = GetRouteVariable<string>(routeData, ControllerKey);
if (controllerName == null)
{
throw new HttpResponseException(HttpStatusCode.NotFound);
}
return controllerName;
}
private static string GetRequestedActionName(IHttpRouteData routeData)
{
return GetRouteVariable<string>(routeData, ActionKey);
}
public IDictionary<string, HttpControllerDescriptor> GetControllerMapping()
{
return _controllers.Value;
}
}
public class IsRestConstraint : IHttpRouteConstraint
{
public bool Match(HttpRequestMessage request, IHttpRoute route, string parameterName, IDictionary<string, object> values,
HttpRouteDirection routeDirection)
{
if (values.ContainsKey(parameterName))
{
string id = values[parameterName] as string;
return string.IsNullOrEmpty(id) || IsRest(id);
}
else
{
return false;
}
}
private bool IsRest(string actionName)
{
bool isRest = false;
Guid guidId;
int intId;
if (Guid.TryParse(actionName, out guidId))
{
isRest = true;
}
else if (int.TryParse(actionName, out intId))
{
isRest = true;
}
return isRest;
}
}
public class IsRpcConstraint : IHttpRouteConstraint
{
public bool Match(HttpRequestMessage request, IHttpRoute route, string parameterName, IDictionary<string, object> values,
HttpRouteDirection routeDirection)
{
if (values.ContainsKey(parameterName))
{
string action = values[parameterName] as string;
return !string.IsNullOrEmpty(action) && IsRpcAction(action);
}
else
{
return false;
}
}
private bool IsRpcAction(string actionName)
{
bool isRpc = true;
Guid guidId;
int intId;
if (Guid.TryParse(actionName, out guidId))
{
isRpc = false;
}
else if (int.TryParse(actionName, out intId))
{
isRpc = false;
}
return isRpc;
}
}
config.MapHttpAttributeRoutes();
config.Services.Replace(typeof(IHttpControllerSelector), new MyHttpControllerSelector(config));
config.Routes.MapHttpRoute(
name: "RpcApi",
routeTemplate: "api/{controller}/{action}/{id}",
defaults: new { id = RouteParameter.Optional },
constraints: new { action = new IsRpcConstraint() }
);
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional },
constraints: new { id = new IsRestConstraint() }
);
api/User/1
api/User/import
api/Tree (TreeController)
api/Tree/1 (TreeController)
api/Tree/grow (TreeRpcController)
api/Dog (DogController)
api/Dog/1 (DogController)
api/Dog/bark (DogRpcController)
{controller}/{action}/{id}
关于c# - 在同一 Controller 上的 Web Api 中多次 POST 调用的最佳实践,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24709402/
#include using namespace std; class C{ private: int value; public: C(){ value = 0;
这个问题已经有答案了: What is the difference between char a[] = ?string?; and char *p = ?string?;? (8 个回答) 已关闭
关闭。此题需要details or clarity 。目前不接受答案。 想要改进这个问题吗?通过 editing this post 添加详细信息并澄清问题. 已关闭 7 年前。 此帖子已于 8 个月
除了调试之外,是否有任何针对 c、c++ 或 c# 的测试工具,其工作原理类似于将独立函数复制粘贴到某个文本框,然后在其他文本框中输入参数? 最佳答案 也许您会考虑单元测试。我推荐你谷歌测试和谷歌模拟
我想在第二台显示器中移动一个窗口 (HWND)。问题是我尝试了很多方法,例如将分辨率加倍或输入负值,但它永远无法将窗口放在我的第二台显示器上。 关于如何在 C/C++/c# 中执行此操作的任何线索 最
我正在寻找 C/C++/C## 中不同类型 DES 的现有实现。我的运行平台是Windows XP/Vista/7。 我正在尝试编写一个 C# 程序,它将使用 DES 算法进行加密和解密。我需要一些实
很难说出这里要问什么。这个问题模棱两可、含糊不清、不完整、过于宽泛或夸夸其谈,无法以目前的形式得到合理的回答。如需帮助澄清此问题以便重新打开,visit the help center . 关闭 1
有没有办法强制将另一个 窗口置于顶部? 不是应用程序的窗口,而是另一个已经在系统上运行的窗口。 (Windows, C/C++/C#) 最佳答案 SetWindowPos(that_window_ha
假设您可以在 C/C++ 或 Csharp 之间做出选择,并且您打算在 Windows 和 Linux 服务器上运行同一服务器的多个实例,那么构建套接字服务器应用程序的最明智选择是什么? 最佳答案 如
你们能告诉我它们之间的区别吗? 顺便问一下,有什么叫C++库或C库的吗? 最佳答案 C++ 标准库 和 C 标准库 是 C++ 和 C 标准定义的库,提供给 C++ 和 C 程序使用。那是那些词的共同
下面的测试代码,我将输出信息放在注释中。我使用的是 gcc 4.8.5 和 Centos 7.2。 #include #include class C { public:
很难说出这里问的是什么。这个问题是含糊的、模糊的、不完整的、过于宽泛的或修辞性的,无法以目前的形式得到合理的回答。如需帮助澄清此问题以便重新打开它,visit the help center 。 已关
我的客户将使用名为 annoucement 的结构/类与客户通信。我想我会用 C++ 编写服务器。会有很多不同的类继承annoucement。我的问题是通过网络将这些类发送给客户端 我想也许我应该使用
我在 C# 中有以下函数: public Matrix ConcatDescriptors(IList> descriptors) { int cols = descriptors[0].Co
我有一个项目要编写一个函数来对某些数据执行某些操作。我可以用 C/C++ 编写代码,但我不想与雇主共享该函数的代码。相反,我只想让他有权在他自己的代码中调用该函数。是否可以?我想到了这两种方法 - 在
我使用的是编写糟糕的第 3 方 (C/C++) Api。我从托管代码(C++/CLI)中使用它。有时会出现“访问冲突错误”。这使整个应用程序崩溃。我知道我无法处理这些错误[如果指针访问非法内存位置等,
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 我们不允许提问寻求书籍、工具、软件库等的推荐。您可以编辑问题,以便用事实和引用来回答。 关闭 7 年前。
已关闭。此问题不符合Stack Overflow guidelines 。目前不接受答案。 要求我们推荐或查找工具、库或最喜欢的场外资源的问题对于 Stack Overflow 来说是偏离主题的,因为
我有一些 C 代码,将使用 P/Invoke 从 C# 调用。我正在尝试为这个 C 函数定义一个 C# 等效项。 SomeData* DoSomething(); struct SomeData {
这个问题已经有答案了: Why are these constructs using pre and post-increment undefined behavior? (14 个回答) 已关闭 6
我是一名优秀的程序员,十分优秀!