我在MVC WebApi中声明了一个方法:
[Route("api/User/LoginUser")]
public string PostLogin(string email, string password, string authkey)
{
// Do Something
return "";
}
现在在用于测试目的的cshtml文件中,我将方法调用为:
function LoginUser() {
$.ajax({
url: baseUrl + "api/User/LoginUser",
type: "Post",
contentType: 'application/json; charset=utf-8',
data: JSON.stringify({ email: "xyz@gmail.com", password: "password", authkey: "1234" }),
dataType: 'json',
success: function (data) {
// Do Soemthing
},
fail: function (data) {
// Failed
}
});
}
但api从未被调用过。我没有遇到问题。请有人帮助我,我在这里遇到了很大的困难。
提前完成。任何形式的帮助将不胜感激。
答案 0 :(得分:2)
让我们做一点检查。创建新的WebApi项目,然后创建一个TestController
扩展ApiController
,然后在其中创建一个包含模型的方法
[HttpPost]
public string SomeThing(string name, string age)
{
return "smth";
}
现在编译应用程序并打开localhost/Help
有关于可用方法的文档。我们的Test
控制器也有记录。让我们看看那里有什么:
Test
API Description
POST api/Test?name={name}&age={age}
No documentation available.
似乎多个参数自动映射为GET参数,而不是从后请求体中的键/值对中提取。这是因为默认HttpParameterBinding
,如果您想要更改它,则需要对其进行扩展,覆盖某些内容并告知您的应用使用精心设计的HttpParameterBinding
覆盖。
幸运的是,有关于如何创建自己的参数绑定的博客文章(http://weblog.west-wind.com/posts/2012/Sep/11/Passing-multiple-simple-POST-Values-to-ASPNET-Web-API)
给予博客作者的所有信用,如果链接被破坏,我将粘贴一些代码。
在应用程序的某处创建一个扩展HttpParameterBinding
public class SimplePostVariableParameterBinding : HttpParameterBinding
{
private const string MultipleBodyParameters = "MultipleBodyParameters";
public SimplePostVariableParameterBinding(HttpParameterDescriptor descriptor)
: base(descriptor)
{
}
/// <summary>
/// Check for simple binding parameters in POST data. Bind POST
/// data as well as query string data
/// </summary>
/// <param name="metadataProvider"></param>
/// <param name="actionContext"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public override Task ExecuteBindingAsync(ModelMetadataProvider metadataProvider,
HttpActionContext actionContext,
CancellationToken cancellationToken)
{
string stringValue = null;
NameValueCollection col = TryReadBody(actionContext.Request);
if (col != null)
stringValue = col[Descriptor.ParameterName];
// try reading query string if we have no POST/PUT match
if (stringValue == null)
{
var query = actionContext.Request.GetQueryNameValuePairs();
if (query != null)
{
var matches = query.Where(kv => kv.Key.ToLower() == Descriptor.ParameterName.ToLower());
if (matches.Count() > 0)
stringValue = matches.First().Value;
}
}
object value = StringToType(stringValue);
// Set the binding result here
SetValue(actionContext, value);
// now, we can return a completed task with no result
TaskCompletionSource<AsyncVoid> tcs = new TaskCompletionSource<AsyncVoid>();
tcs.SetResult(default(AsyncVoid));
return tcs.Task;
}
/// <summary>
/// Method that implements parameter binding hookup to the global configuration object's
/// ParameterBindingRules collection delegate.
///
/// This routine filters based on POST/PUT method status and simple parameter
/// types.
/// </summary>
/// <example>
/// GlobalConfiguration.Configuration.
/// .ParameterBindingRules
/// .Insert(0,SimplePostVariableParameterBinding.HookupParameterBinding);
/// </example>
/// <param name="descriptor"></param>
/// <returns></returns>
public static HttpParameterBinding HookupParameterBinding(HttpParameterDescriptor descriptor)
{
var supportedMethods = descriptor.ActionDescriptor.SupportedHttpMethods;
// Only apply this binder on POST and PUT operations
if (supportedMethods.Contains(HttpMethod.Post) ||
supportedMethods.Contains(HttpMethod.Put))
{
var supportedTypes = new Type[] { typeof(string),
typeof(int),
typeof(decimal),
typeof(double),
typeof(bool),
typeof(DateTime),
typeof(byte[])
};
if (supportedTypes.Where(typ => typ == descriptor.ParameterType).Count() > 0)
return new SimplePostVariableParameterBinding(descriptor);
}
return null;
}
private object StringToType(string stringValue)
{
object value = null;
if (stringValue == null)
value = null;
else if (Descriptor.ParameterType == typeof(string))
value = stringValue;
else if (Descriptor.ParameterType == typeof(int))
value = int.Parse(stringValue, CultureInfo.CurrentCulture);
else if (Descriptor.ParameterType == typeof(Int32))
value = Int32.Parse(stringValue, CultureInfo.CurrentCulture);
else if (Descriptor.ParameterType == typeof(Int64))
value = Int64.Parse(stringValue, CultureInfo.CurrentCulture);
else if (Descriptor.ParameterType == typeof(decimal))
value = decimal.Parse(stringValue, CultureInfo.CurrentCulture);
else if (Descriptor.ParameterType == typeof(double))
value = double.Parse(stringValue, CultureInfo.CurrentCulture);
else if (Descriptor.ParameterType == typeof(DateTime))
value = DateTime.Parse(stringValue, CultureInfo.CurrentCulture);
else if (Descriptor.ParameterType == typeof(bool))
{
value = false;
if (stringValue == "true" || stringValue == "on" || stringValue == "1")
value = true;
}
else
value = stringValue;
return value;
}
/// <summary>
/// Read and cache the request body
/// </summary>
/// <param name="request"></param>
/// <returns></returns>
private NameValueCollection TryReadBody(HttpRequestMessage request)
{
object result = null;
// try to read out of cache first
if (!request.Properties.TryGetValue(MultipleBodyParameters, out result))
{
var contentType = request.Content.Headers.ContentType;
// only read if there's content and it's form data
if (contentType == null || contentType.MediaType != "application/x-www-form-urlencoded")
{
// Nope no data
result = null;
}
else
{
// parsing the string like firstname=Hongmei&lastname=ASDASD
result = request.Content.ReadAsFormDataAsync().Result;
}
request.Properties.Add(MultipleBodyParameters, result);
}
return result as NameValueCollection;
}
private struct AsyncVoid
{
}
}
然后在Startup.cs
中调用全局配置并在所有param绑定规则之前插入,通过调用工厂方法HookupParameterBinding
GlobalConfiguration.Configuration.ParameterBindingRules.Insert(
0,
SimplePostVariableParameterBinding.HookupParameterBinding
);
现在重新编译应用程序并再次检查帮助页面。您现在控制器不要求您将方法签名作为GET请求发送
Test
API Description
POST api/Test
No documentation available.
现在尝试我们的方法,就像他们在博客中尝试的那样
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
<form>
Name: <input type="text" id="name" value="ggg" />
Age: <input type="text" id="age" value="ddd" />
<input type="button" id="btnSend" value="Send" />
</form>
<script type="text/javascript">
$("#btnSend").click(function () {
$.ajax({
url: "http://localhost:50931/api/Test",
type: "POST",
data: {
name: $("#name").val(),
age: $("#age").val()
},
success: function(response) {
alert(response)
}
});
});
</script>
点击按钮,我们收到一条提示smth
的警告,因为我们“返回”smth“
如果我们打开freibug控制台并跟踪我们通过jquery发送的内容,我们将看到
POST http://localhost:50931/api/Test
200 OK
2ms
jquery-1.10.2.js (line 8720)
HeadersPostResponseJSONCookies
Parametersapplication/x-www-form-urlencodedDo not sort
age
ddd
name
ggg
作为替代方案,我们可以使用简单的json序列化,因此我们可以使方法签名期望JObject
using Newtonsoft.Json.Linq;
public class TestController : ApiController
{
[HttpPost]
public string SomeThing(JObject obj)
{
return obj["name"] + " bla " + obj["age"];
}
}
如果我们针对此方法执行POST,就像上面的HTML一样,我们会收到ddd bla ggg
的提醒。
答案 1 :(得分:0)
您将数据作为json对象发送,但您的操作参数是预期在网址中找到的简单类型。 尝试为POST创建一个复杂的对象。
public class LoginUser
{
public string email { get; set; }
public string password{ get; set; }
public string authkey{ get; set; }
}
并将您的Api操作更改为
[Route("api/User/LoginUser")]
public string PostLogin(LoginUser user)
{
string email - user.email;
string password- user.email;
string authkey- user.email;
return "";
}