When I send a request from Android to ASP.NET method there is an error:
W/DefaultRequestDirector﹕ Authentication error: Unable to respond to any of these challenges: {}
W/MainActivity﹕ Error 401 for URL
I/jsonResultStr :﹕ {"Message":"There was an error processing the request.","StackTrace":"","ExceptionType":""}
This is the ASP.NET method prototype:
public string GetBuildingData(string roadId)
This is the Android sendToAsp method:
public void sendToAsp() {
HttpPost httpPost = new HttpPost("http://madenati.alameentech.com:8082/Coding/Services/BuildingsServices.asmx/GetBuildingData");
httpPost.setHeader("content-type", "application/json");
HttpClient httpClient = new DefaultHttpClient(getHttpParameterObj(4000,4000));
JSONObject data = new JSONObject();
try {
data.put("roadId", "1");
StringEntity entity = new StringEntity(data.toString(), HTTP.UTF_8);
httpPost.setEntity(entity);
HttpResponse response = httpClient.execute(httpPost);
BufferedReader reader = new BufferedReader(new InputStreamReader(response.getEntity().getContent(), "UTF-8"));
String jsonResultStr = reader.readLine();
data = new JSONObject(jsonResultStr);
final int statusCode = response.getStatusLine().getStatusCode();
if (statusCode != HttpStatus.SC_OK) {
Log.w(getClass().getSimpleName(), "Error " + statusCode + " for URL " );
}
Log.i("jsonResultStr : ",jsonResultStr);
} catch(Exception e) {
Log.v("Exception","Exception sendToAsp");
}
}
This is getHttpParameterObj method:
private HttpParams getHttpParameterObj(int timeOutConnection,int timeOutSocket)
{
HttpParams httpParameters = new BasicHttpParams();
HttpConnectionParams.setConnectionTimeout(httpParameters, timeOutConnection);
HttpConnectionParams.setSoTimeout(httpParameters, timeOutSocket);
return httpParameters;
}
and in Manifest.xml
<uses-permission android:name="android.permission.INTERNET" />
What could be the problem?
Use this class to do request:
package com.alameen.mat;
import android.app.Activity;
import android.os.AsyncTask;
import android.util.Log;
import org.ksoap2.SoapEnvelope;
import org.ksoap2.SoapFault;
import org.ksoap2.serialization.SoapObject;
import org.ksoap2.serialization.SoapSerializationEnvelope;
import org.ksoap2.transport.HttpTransportSE;
public class WebService extends AsyncTask<String, String, String>
{
public String NameSpace = "";
public String MethodName = "";
SoapObject request;
SoapSerializationEnvelope envelope;
HttpTransportSE androidHttpTransport;
String URL="";
Activity context;
public WebService(Activity c, String nameSpace, String method, String url)
{
context=c;
NameSpace=nameSpace;
MethodName=method;
request = new SoapObject(NameSpace, MethodName);
envelope = new SoapSerializationEnvelope(SoapEnvelope.VER12);
envelope.setOutputSoapObject(request);
envelope.dotNet = true;
URL=url;
androidHttpTransport = new HttpTransportSE(URL,30000);
}
public void addProperty(String name,String val)
{
request.addProperty(name,val);
}
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
//Log.i("jsonArray from ASP.NET: ",result);
}
#Override
protected void onPreExecute() {
super.onPreExecute();
}
#Override
protected String doInBackground(String... params) {
try
{
androidHttpTransport.call(params[0], envelope);
SoapObject result = (SoapObject)envelope.bodyIn;
String res = result.getProperty(0).toString();
//Log.d("result", res);
return res;
}
catch(Exception e)
{
SoapFault fault = (SoapFault)envelope.bodyIn;
Log.d("error", fault.getMessage()+"/"+fault.getCause());
e.printStackTrace();
}
return null;
}
void log(String l)
{
Log.d("status", l);
}
}
call like this:
public static String URL="http://... .asmx?WSDL";
WebService ws = new WebService(This, "http://tempuri.org/", "methodName", URL);
and import this library to your project:
https://www.dropbox.com/s/j5bi6yt8x5xpdbk/ksoap2-android-assembly-2.6.0-jar-with-dependencies.jar?dl=0
Related
The rest API server is under "Spring boot", the client is under XAMARIN FORM and I use HttpClient to get or post data to the server.
Is there a specific format that must be sent by a rest API in case of an error to fill, in HttpClient, the ReasonPhrase? Because the ReasonPhrase is always empty even on error.
the format I send from the rest API is normally a standard like this :
{
"timestamp": "2022-09-11T17:58:02.811+00:00",
"status": 404,
"error": "Not Found",
"message": "No message available",
}
In the example, the reasonPhrase should have "No message available"
SPRING BOOT code
My Exception Handler code:
#ControllerAdvice
public class AppExceptionsHandler extends ResponseEntityExceptionHandler {
// Handle a specific error
#ExceptionHandler(value = { ApplicationException.class })
public ResponseEntity<Object> handleUserServiceException(ApplicationException ex, WebRequest request) {
ErrorMessage errorMessage = new ErrorMessage(new Date(), HttpStatus.INTERNAL_SERVER_ERROR, ex.getMessage());
return new ResponseEntity<>(errorMessage, new HttpHeaders(), HttpStatus.INTERNAL_SERVER_ERROR);
}
// Handle unknown error
#ExceptionHandler(value = { Exception.class })
public ResponseEntity<Object> handleOtherExceptions(Exception ex, WebRequest request) {
ErrorMessage errorMessage = new ErrorMessage(new Date(), ex.getMessage());
return new ResponseEntity<>(errorMessage, new HttpHeaders(), HttpStatus.INTERNAL_SERVER_ERROR);
}
}
My Exception code:
public class ApplicationException extends RuntimeException{
private static final long serialVersionUID = 7289264700624277238L;
public ApplicationException(String message)
{
super(message);
}
}
My error message object code:
public class ErrorMessage {
private Date timestamp;
private HttpStatus status;
private String message;
public ErrorMessage() {}
public ErrorMessage(Date timestamp, HttpStatus status, String message)
{
this();
this.timestamp = timestamp;
this.message = message;
this.status = status;
}
*** some more code getter and setter ***
}
When I throw the exception in the code:
*** some code ***
throw new ApplicationException("Wrong user");
Xamarin code
internal class HttpMethods
{
private HttpClient _httpClient;
public HttpMethods()
{
_httpClient = new HttpClient();
_httpClient.Timeout = TimeSpan.FromSeconds(15);
_httpClient.MaxResponseContentBufferSize = 256000;
_httpClient.DefaultRequestHeaders.Add("Accept", "application/json");
}
public async Task<(TA, ErrorDto)> HttpPost<TA, TB>(string url, string token, TB data)
{
var result = default(TA);
var error = new ErrorDto();
HttpResponseMessage response = new();
_httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);
HttpContent content;
content = FileContent(data as string);
response = await _httpClient.PostAsync(new Uri(url), content);
if (response.IsSuccessStatusCode)
{
var jsonDataResponse = await response.Content.ReadAsStringAsync();
result = JsonConvert.DeserializeObject<TA>(jsonDataResponse);
}
else
{
error.ReasonPhrase = (int)response.StatusCode;
error.StatusCode = (string)response.ReasonPhrase;
}
return (result, error);
}
}
Thanks for your help
PS: Edited for code details.
well I am trying to develop a soap client, it wanted its custom soapheader(i.e.usercred) to serialized, but after doing so I get this as error
System.Runtime.Serialization.InvalidDataContractException: 'Type 'ConsoleApp1.Program+usercred' cannot inherit from a type that is not marked with DataContractAttribute or SerializableAttribute. Consider marking the base type System.Web.Services.Protocols.SoapHeader with DataContractAttribute or SerializableAttribute, or removing them from the derived type.'
it kinda wants soapheader to be also serialized plz help
There are several ways to add custom soup header in your soup request.
For example you can create soup request using HTTPRequest where you can build soup envelope as you want. Client to send SOAP request and receive response
public override string Process(string UserName,string Password)
{
string uri = "https://serviceURL";
HttpWebRequest req = (HttpWebRequest)WebRequest.CreateDefault(new Uri(uri));
req.ContentType = "application/soap+xml; charset=utf-8";
req.Method = "POST";
string soapRequest = BuildSoapRequest(UserName,Password);
StreamWriter stm = new StreamWriter(req.GetRequestStream(), Encoding.UTF8);
stm.Write(soapRequest);
stm.Close();
try
{
HttpWebResponse wr = (HttpWebResponse)req.GetResponse();
StreamReader srd = new StreamReader(wr.GetResponseStream());
string response = srd.ReadToEnd();
return ExtractResponse(response);
}
catch (WebException e)
{
string error = "";
HttpWebResponse errRsp = (HttpWebResponse)e.Response;
if (errRsp != null)
{
using (StreamReader rdr = new StreamReader(errRsp.GetResponseStream()))
{
string line;
while ((line = rdr.ReadLine()) != null)
{
error += line;
}
}
}
throw new Exception(e.Message + "<br/> " + error);
}
catch (Exception e)
{
throw e;
}
}
private string BuildSoapRequest(string UserName,string Password)
{
StringBuilder soapRequest = new StringBuilder();
soapRequest.Append("<soap:Envelope xmlns:cor=\"http://www.caqh.org/SOAP/WSDL/CORERule2.2.0.xsd\" xmlns:soap=\"http://www.w3.org/2003/05/soap-envelope\" xmlns:tem=\"http://tempuri.org/\">");
soapRequest.Append("<soap:Header>");
soapRequest.Append("<wsse:Security xmlns:wsse=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd\" xmlns:wsu=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd\">");
soapRequest.Append("<wsse:UsernameToken>");
soapRequest.Append("<wsse:Username>" + UserName + "</wsse:Username>");
soapRequest.Append("<wsse:Password>" + Password + "</wsse:Password>");
soapRequest.Append("</wsse:UsernameToken>");
soapRequest.Append("</wsse:Security>");
soapRequest.Append("</soap:Header>");
soapRequest.Append("<soap:Body>");
soapRequest.Append("</soap:Body>");
soapRequest.Append("</soap:Envelope>");
return soapRequest.ToString();
}
private static string ExtractResponse(string soap)
{
}
If you are consuming WCF service then you can add custom behavior in your request.
Custom Endpoint Behavior not being used in WCF Client with Service Reference
public class CustomClientBehavior : IEndpointBehavior
{
string _username;
string _password;
public CustomClientBehavior(string username, string password)
{
_username = username;
_password = password;
}
public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters)
{
}
public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime)
{
CustomInspector inspector = new CustomInspector(_username, _password);
clientRuntime.MessageInspectors.Add(inspector);
}
public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
{
}
public void Validate(ServiceEndpoint endpoint)
{
}
}
public class CustomClientBehaviorExtensionElement : BehaviorExtensionElement
{
string _username;
string _password;
public CustomClientBehaviorExtensionElement(string username, string password)
{
_username = username;
_password = password;
}
public override Type BehaviorType
{
get { return typeof(CustomClientBehavior); }
}
protected override object CreateBehavior()
{
return new CustomClientBehavior(_username, _password);
}
}
public class CustomInspector : IClientMessageInspector
{
string _username;
string _password;
public CustomInspector(string username, string password)
{
_username = username;
_password = password;
}
public void AfterReceiveReply(ref Message reply, object correlationState)
{
return;
}
public object BeforeSendRequest(ref Message request, IClientChannel channel)
{
request.Headers.Clear();
string headerText = "<wsse:UsernameToken xmlns:wsse=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd\">" +
"<wsse:Username>{0}</wsse:Username>" +
"<wsse:Password Type=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText\">" +
"{1}</wsse:Password>" +
"</wsse:UsernameToken>";
headerText = string.Format(headerText, _username, _password);
XmlDocument MyDoc = new XmlDocument();
MyDoc.LoadXml(headerText);
XmlElement myElement = MyDoc.DocumentElement;
System.ServiceModel.Channels.MessageHeader myHeader = MessageHeader.CreateHeader("Security", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd", myElement, false);
request.Headers.Add(myHeader);
return Convert.DBNull;
}
}
Test Client should be like
TestService.Client objClient = new TestService.Client();
objClient.Endpoint.Behaviors.Add(new CustomClientBehavior(UserName, Password));
You can also try WebService Headers Authentication
i am trying to make an asynchronous call to a webservice.
I would like to make this call when opening the app (App.xaml.cs).
According to the answer that comes back to me, it has to navigate to a particular page
But I do not work.
public partial class App : PrismApplication
{
public App(IPlatformInitializer initializer = null) : base(initializer) { }
protected override void OnInitialized()
{
InitializeComponent();
try
{
CheckLogin().Wait();
}
catch (Exception e)
{
var t = e;
}
}
private static async Task CheckLogin()
{
try
{
var login = new Login
{
Email = "test#test.com",
Password = "test",
};
var client = new HttpClient { BaseAddress = new Uri("http://www.api.com/test/") };
var data = JsonConvert.SerializeObject(login);
var content = new StringContent(data, Encoding.UTF8, "application/json");
var response = await client.PostAsync(#"api/it-IT/auth/token", content); //crash without error, freeze
if (response.IsSuccessStatusCode)
{
var successResult = JsonConvert.DeserializeObject<HttpResponseMessage>(response.Content.ReadAsStringAsync().Result);
if (successResult != null)
{
//return true;
}
else
{
//return false;
}
}
}
catch (Exception e)
{
var t = e;
}
}
protected override void RegisterTypes()
{
Container.RegisterTypeForNavigation<NavigationPage>();
Container.RegisterTypeForNavigation<MainPage>();
Container.RegisterTypeForNavigation<MainPage2>();
Container.RegisterTypeForNavigation<MainPage3>();
}
}
When does the postasync call does not go more forward, not I get no errors, but does not proceed.
But if I try the same code in an application console, everything works fine, why?
class Program
{
static void Main(string[] args)
{
Console.WriteLine("A");
CheckLogin().Wait();
Console.WriteLine("K");
Console.ReadKey();
}
private static async Task CheckLogin()
{
try
{
var login = new Login
{
Email = "test#test.com",
Password = "#test",
};
var client = new HttpClient { BaseAddress = new Uri("http://www.api.com/test/") };
var data = JsonConvert.SerializeObject(login);
var content = new StringContent(data, Encoding.UTF8, "application/json");
var response = await client.PostAsync(#"api/it-IT/auth/token", content);
if (response.IsSuccessStatusCode)
{
}
}
catch (Exception e)
{
var t = e;
}
}
}
If I try to do the same operation within a command with wait I do not work the same error, but if I do await, it will work fine, but in App.xaml.cs in OnInitialized() I can not put await
public DelegateCommand callCommand { get; set; }
public MainPage2ViewModel()
{
callCommand = new DelegateCommand(Call);
}
private void Call()
{
//await CheckLogin(); // work
CheckLogin().Wait(); // not work the same problem
var i = "pippo";
}
private async Task CheckLogin()
{
....
}
Is there anything to set with xamarin or with prism?
I've also the same strange error...
i fix with this workaround (use an async void that wrap async task)...
public App()
{
InitializeComponent();
Current.MainPage = new LoadingPage();
}
protected override void OnStart()
{
MagicInit();
base.OnStart();
}
public static async void MagicInit()
{
var f = await FileSystem.Current.LocalStorage.CreateFileAsync("db.sqlite", CreationCollisionOption.OpenIfExists);
DbConnection = f.Path;
await DataService.DbFill();
User = await DataService.Instance.Table<SpUser>().FirstOrDefaultAsync();
Current.MainPage = User != null ? (Page)new MainPage() : new LoginPage();
}
I'm trying to create a dummy web api with authentication
by following this link : YouTube Video Tutorial Link
Controller Code :
MySecurityClient msc = new MySecurityClient();
ViewBag.result1 = msc.Demo()==null ?"Access Denied": msc.Demo();
return View();
In Model:
public class MySecurityClient
{
private string BASE_URL = "http://localhost:3513/api/MySecurity/";
private object convert;
public string Demo()
{
try
{
HttpClient Client = new HttpClient();
var authInfo = Convert.ToBase64String(Encoding.Default.GetBytes("acc1:123"));
Client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", authInfo);
Client.BaseAddress = new Uri(BASE_URL);
HttpResponseMessage response = Client.GetAsync("Work2").Result;
if (response.IsSuccessStatusCode)
return response.Content.ReadAsStringAsync().Result;
return null;
}
catch (Exception ex)
{
return null;
}
}
}
Server Controller :
[HttpGet]
[Route("Work2")]
[MyAuthorize(Roles="SuperAdmin")]
public string Work2()
{
return "Work2";
}
Authorization Override:
public override void OnAuthorization(HttpActionContext actionContext)
{
try
{
AuthenticationHeaderValue authValue = actionContext.Request.Headers.Authorization;
if (authValue != null && !string.IsNullOrWhiteSpace(authValue.Parameter)
&& authValue.Scheme == BasicAuthResponseHeaderValue)
{
Credential parsedCredentials = ParseAuthorizationHeader(authValue.Parameter);
var MyPrincipal = new MyPrincipal(parsedCredentials.UserName);
if (!MyPrincipal.IsInRole(Roles))
{
actionContext.Response = actionContext.Request.CreateResponse(HttpStatusCode.Unauthorized);
actionContext.Response.Headers.Add(BasicAuthResponseHeader, BasicAuthResponseHeaderValue);
}
else
{
actionContext.Response = actionContext.Request.CreateResponse(HttpStatusCode.OK);
actionContext.Response.Headers.Add(BasicAuthResponseHeader, BasicAuthResponseHeaderValue);
//return;
}
}
}
catch (Exception ex)
{
actionContext.Response = actionContext.Request.CreateResponse(HttpStatusCode.OK);
actionContext.Response.Headers.Add(BasicAuthResponseHeader, BasicAuthResponseHeaderValue);
}
}
response.IsSuccessStatusCode is true,
but ViewBag.result1 is empty if we use return response.Content.ReadAsAsync<string>().Result;
and Access Denied on return response.Content.ReadAsAsync<string>().Result;
Thanks in advance
I try understand how work with api (based on api.vk.com).
I have created ASP.NET MVC 4 empty project.
It part of Controller:
public ActionResult LoginVk()
{
vkProvider = new VKProvider();
vkProvider.Config = new VkAppConfig { AppKey = "5572789", AppSecret = "i2OpN7gj62ddwTqqRJrK" };
return Redirect(vkProvider.Authorize("http://localhost:56287/User/Access"));
}
public string Authorize(string redirectTo)
{
return string.Format(AuthorizeUri, Config.AppKey, redirectTo);
}
public ActionResult Access()
{
if (Request.Params.AllKeys.Contains("code"))
{
var code = Request.Params["code"];
if (ProcessVkCode(code))
{
return RedirectToAction("List");
}
}
return View("Error");
}
protected bool ProcessVkCode(string code)
{
if (vkProvider.GetAccessToken(code))
{
var jsonVkAccess = JsonConvert.SerializeObject(vkProvider.AccessToken);
var jObj = vkProvider.GetUserInfo();
var vkUser = new User
{
FirstName = jObj.ToString(),
LastName = jsonVkAccess.ToString()
};
repository.SaveUser(vkUser);
return true;
}
return false;
}
It's part of model VKProvider:
public static string AuthorizeUri =
"http://api.vkontakte.ru/oauth/authorize?client_id={0}&scope=photos,offline,wall,groups&redirect_uri={1}&response_type=code";
public static string GetTokenUri =
"https://api.vkontakte.ru/oauth/access_token?client_id={0}&client_secret={1}&code={2}";
public bool GetAccessToken(string Code)
{
try
{
string reqStr = string.Format(GetTokenUri, Config.AppKey, Config.AppSecret, Code);
ServicePointManager.ServerCertificateValidationCallback += (sender, certificate, chain, sslPolicyErrors) => true;
WebClient webClient = new WebClient();
var response = webClient.DownloadString(reqStr);
AccessToken = JsonConvert.DeserializeObject<VkAccessToken>(response);
return true;
}
catch (WebException ex)
{
return false;
}
}
Application return error (401) Unauthorized when execute webClient.DownloadString(reqStr). What is wrong?