问题
I am trying to insert the record using asp.net web-services from the android platform using retrofit. I have already tried many solutions but not able to get success.
Basically in my asp.net web service code is:
[WebMethod]
[ScriptMethod(ResponseFormat = ResponseFormat.Json)]
public void insertEducationAPI(int user_id, string degree_name, string institute_name, string board_university_name, int year_of_passing, float percentage_cgpa, string specialization)
{
HttpContext.Current.Response.AddHeader("Access-Control-Allow-Origin", "*");
if (HttpContext.Current.Request.HttpMethod == "OPTIONS")
{
//These headers are handling the "pre-flight" OPTIONS call sent by the browser
HttpContext.Current.Response.AddHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE");
HttpContext.Current.Response.AddHeader("Access-Control-Allow-Headers", "Content-Type, Accept");
HttpContext.Current.Response.AddHeader("Access-Control-Max-Age", "1728000");
HttpContext.Current.Response.End();
}
Education edu = new Education();
string result = educationModel.addEducation(user_id, degree_name, institute_name, board_university_name, year_of_passing, percentage_cgpa, specialization);
JavaScriptSerializer js = new JavaScriptSerializer();
Context.Response.Clear();
Context.Response.ContentType = "application/json";
if (result.Equals("complete"))
{
edu.err = false;
edu.err_message = "Inserted success";
}
else
{
edu.err = true;
edu.err_message = "Fail";
}
Context.Response.Write(js.Serialize(edu));
}
And at android side
API interface:
@Headers({
"Accept: application/json",
"Content-Type: application/json"
})
@FormUrlEncoded
@POST("/EducationApi.asmx/insertEducationAPI")
public void insertEducationDetail(@Field("user_id") int user_id, @Field("degree_name") String degree_name, @Field("institute_name") String institute_name, @Field("board_university_name") String board_university_name, @Field("year_of_passing") int year_of_passing, @Field("percentage_cgpa") float percentage_cgpa, @Field("specialization") String specialization, Callback<Education> callback);
}
Method calling;
retro.getService().insertEducationDetail(1, "MCA", "SRIMCA", "UTU", 2015, 85, ".NET", new Callback<Education>() {
@Override
public void success(Education education, Response response) {
Toast.makeText(Dashboard.this, "success", Toast.LENGTH_SHORT).show();
}
@Override
public void failure(RetrofitError error) {
Toast.makeText(Dashboard.this, error.getMessage(), Toast.LENGTH_SHORT).show();
}
});
Error:
I/System.out: [OkHttp] sendRequest<<
D/GraphicBuffer: register, handle(0x87d71180) (w:720 h:1440 s:736 f:0x1 u:b00)
D/Retrofit: <--- HTTP 500 http://192.168.43.25:81/EducationApi.asmx/insertEducationAPI (77ms)
: HTTP/1.1 500 Internal Server Error
Cache-Control: private
D/Retrofit: Content-Length: 91
Content-Type: application/json; charset=utf-8
Date: Sat, 10 Aug 2019 20:36:09 GMT
D/Retrofit: jsonerror: true
D/Retrofit: Server: Microsoft-IIS/10.0
X-Android-Received-Millis: 1565469369999
X-Android-Response-Source: NETWORK 500
X-Android-Selected-Protocol: http/1.1
X-Android-Sent-Millis: 1565469369982
X-AspNet-Version: 4.0.30319
X-Powered-By: ASP.NET
D/Retrofit: {"Message":"There was an error processing the request.","StackTrace":"","ExceptionType":""}
<--- END HTTP (91-byte body)
How can I solve this problem?
回答1:
On the Android side your API interface looks incorrect:
@POST("/EducationApi.asmx/addEducationAPI")
public void addEducation(@Body List<Education> education, Callback<Education> callback);
It's not a List<Education> on the server side, just a single Education object, so the definition should probably be:
@POST("/EducationApi.asmx/addEducationAPI")
public void addEducation(@Body Education education, Callback<Education> callback);
== edit ==
Also, you have only decorated your API method with [WebMethod] so it only accepts SOAP+XML input. To be callable with JSON you need to add the [ScriptMethod] decoration, e.g.:
[WebMethod]
[ScriptMethod]
public void addEducationAPI(Education education)
{
//...
}
Due to security requirements of the [ScriptMethod] attribute (see JSON Hijacking and How ASP.NET AJAX 1.0 Avoids these Attacks) you need to ensure that your Retrofit requests include a Content-Type: application/json header. e.g.:
@Headers("Content-Type: application/json")
@POST("/EducationApi.asmx/addEducationAPI")
public void addEducation(@Body Education education, Callback<Education> callback);
You should also add an Accept: application/json header if Retrofit isn't already doing that for you. e.g.:
@Headers({
"Accept: application/json",
"Content-Type: application/json"
})
@POST("/EducationApi.asmx/addEducationAPI")
public void addEducation(@Body Education education, Callback<Education> callback);
Including both of these headers in your requests will allow you to delete your JavaScriptSerializer code, and just return an instance of Education. When using [ScriptMethod] the ASP.NET web service framework will automatically return SOAP+XML for SOAP+XML requests and return JSON for JSON requests.
So a full working example, which also includes the [ScriptService] attribute on the EducationApi class, looks like:
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[ScriptService]
public class EducationApi : WebService
{
EducationModel educationModel = new EducationModel();
[WebMethod]
[ScriptMethod]
public Education addEducationAPI(Education education)
{
Education edu = new Education();
string result = educationModel.addEducation(
education.user_id,
education.degree_name,
education.institute_name,
education.board_university_name,
education.year_of_passing,
education.percentage_cgpa,
education.specialization);
if (result.Equals("complete"))
{
edu.err = false;
edu.err_message = "Inserted success";
}
else
{
edu.err = true;
edu.err_message = "Fail";
}
return edu;
}
}
And posting data to it with the curl utility:
curl --data '{"education":{"__type":"Education","user_id":1,"degree_name":"MCA","institute_name":"SRIMCA","board_university_name":"UTU","year_of_passing":2015,"specialization":"None","percentage_cgpa":85}}' --header "Content-Type: application/json" --header "Accept: application/json" --trace-ascii - http://127.0.0.1:8080/EducationApi.asmx/addEducationAPI
Returns the JSON result:
{"d":{"user_id":0,"degree_name":null,"institute_name":null,"board_university_name":null,"year_of_passing":0,"specialization":null,"percentage_cgpa":0,"err":false,"err_message":"Inserted success"}}
来源:https://stackoverflow.com/questions/57439576/how-to-fix-500-internal-server-error-in-retrofit-and-web-services-in-asp-net-w