在cshtml文件中调用具有多个参数的Post方法
本文关键字:参数 Post 方法 文件 cshtml 调用 | 更新日期: 2023-09-27 18:05:26
我已经在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永远不会被调用。我不明白这个问题。谁来帮帮我吧,我被卡在这儿了。
提前感谢。如有任何帮助,不胜感激。
让我们做一个小检查。创建一个新的WebApi项目,然后创建一个扩展ApiController
的TestController
,然后用你的模型在其中创建一个方法
[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参数,而不是从post请求体的键/值对中提取。这是因为默认的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
中调用全局配置并在所有参数绑定规则之前插入您自己的规则(在结构中的第一个位置),通过调用工厂方法HookupParameterBinding
GlobalConfiguration.Configuration.ParameterBindingRules.Insert(
0,
SimplePostVariableParameterBinding.HookupParameterBinding
);
现在重新编译应用程序并再次检查帮助页面。您的控制器现在不要求您将方法签名作为GET请求发送
Test
API Description
POST api/Test
No documentation available.
现在尝试我们的方法,就像他们在blogpost
中尝试的那样 <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
的警告。
您正在发送您的数据作为json对象,但是您的动作参数是简单的类型,它期望在url中找到。试着为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 "";
}