i'm trying to call a restclient in the method including the parsing of data, her's my code which i want to make all of it in the method,any ideas please :
public void Convert(object value, Type targetType, object parameter, CultureInfo culture){RestClient client = new RestClient();
client.BaseUrl = "http://";
RestRequest request = new RestRequest();
request.Method = Method.GET;
request.AddParameter("action", "REE");
request.AddParameter("atm_longitude", location.Longitude);
client.ExecuteAsync(request, ParseFeedCallBack_ListDistance);}
public void ParseFeedCallBack_ListDistance(IRestResponse response){
if (response.StatusCode == HttpStatusCode.OK)
{
ParseXMLFeedDistance(response.Content);
}
private string ParseXMLFeedDistance(string feed)
{
.... return myvalueToBind;
}
i did somthing like this,but it don't call ParseXMLFeedDistance for every item :
foreach (var resp in xmlItems2.Descendants("result"))
{
RestClient client = new RestClient();
client.BaseUrl = "http://";
RestRequest request = new RestRequest();
request.Method = Method.GET;
request.AddParameter("action", "atms_distances");
request.AddParameter("lang", "ar");
request.AddParameter("mode", "xml");
request.AddParameter("appli", "WP");
request.AddParameter("mobile_latitude", "35.843283");
request.AddParameter("mobile_longitude", "10.61617");
request.AddParameter("atm_latitude", resp.Element("Lattitude"));
request.AddParameter("atm_longitude",resp.Element("longitude"));
// client.ExecuteAsync(request, ParseFeedCallBack_ListDistance);
client.ExecuteAsync(request, response =>
{
ParseXMLFeedDistance(response.Content);
});
}
private void ParseXMLFeedDistance(string feed)
{
if (feed == null)
return;
try
{
XElement xmlItems = XElement.Parse(feed);
XDocument xmlItems2 = XDocument.Parse(feed);
var list = new List<State>();
foreach (XElement val in xmlItems2.Descendants("result").Last().Elements())
{
// distance = val.Value;
list.Add(new State
{
TotalDistance = val.Value,
});
}
ResultSearch_ListDistance.ItemsSource = list;
}
catch
{
}
}
Related
I am using monkey chat in my mobile application(Xamrin forms based). While sending a message on IOS, on a real device, I have to click the send button 2 times. First time when I click, it minimizes the keyboard and 2nd time, it sends the message. Please suggest.
How do I send a message on one click?
Here is my send message function
namespace Budocode.ViewModels
{
public class MainChatViewModel : BaseViewModel
{
public ObservableRangeCollection Messages { get; }
ITwilioMessenger twilioMessenger;
string outgoingText = string.Empty;
public string OutGoingText
{
get { return outgoingText; }
set { SetProperty(ref outgoingText, value); }
}
public ICommand SendCommand { get; set; }
public ICommand LocationCommand { get; set; }
public MainChatViewModel()
{
// Initialize with default values
twilioMessenger = DependencyService.Get<ITwilioMessenger>();
Messages = new ObservableRangeCollection<ChatMessage>();
SendCommand = new Command(() =>
{
var message = new ChatMessage
{
Text = OutGoingText,
IsIncoming = false,
ProfileId = "profile" + GlobalSettingsDataSource.Current.SelectedProfileImageId + ".png",
MessageDateTime = DateTime.Now,
FromUser = GlobalSettingsDataSource.Current.SelectedProfile
};
if (string.IsNullOrWhiteSpace(OutGoingText))
return;
Messages.Add(message);
twilioMessenger?.SendMessage(message.Text, message.ProfileId, GlobalSettingsDataSource.Current.SelectedProfile);
OutGoingText = string.Empty;
});
LocationCommand = new Command(async () =>
{
try
{
var local = await CrossGeolocator.Current.GetPositionAsync(TimeSpan.FromSeconds(15));
var map = $"https://maps.googleapis.com/maps/api/staticmap?center={local.Latitude.ToString(CultureInfo.InvariantCulture)},{local.Longitude.ToString(CultureInfo.InvariantCulture)}&zoom=17&size=400x400&maptype=street&markers=color:red%7Clabel:%7C{local.Latitude.ToString(CultureInfo.InvariantCulture)},{local.Longitude.ToString(CultureInfo.InvariantCulture)}&key=";
var message = new ChatMessage
{
Text = "I am here",
AttachementUrl = map,
ProfileId = "profile" + GlobalSettingsDataSource.Current.SelectedProfileImageId + ".png",
IsIncoming = false,
MessageDateTime = DateTime.Now
};
Messages.Add(message);
twilioMessenger?.SendMessage("attach:" + message.AttachementUrl, message.ProfileId, GlobalSettingsDataSource.Current.SelectedProfile);
}
catch (Exception ex)
{
}
});
if (twilioMessenger == null)
return;
twilioMessenger.MessageAdded = (message) =>
{
//if (message.ProfileId == "Icon.png")
Device.BeginInvokeOnMainThread(() =>
{
if (message.FromUser != GlobalSettingsDataSource.Current.SelectedProfile)
{
message.IsIncoming = true;
}
else
{
message.IsIncoming = false;
}
Messages.Add(message);
});
};
}
public async void InitializeMock(string channelName)
{
try
{
var id = CrossDeviceInfo.Current.Id;
var userId = PersistantData.Current.UserAccount.Properties["user_id"];
HttpResponseMessage appResponse = CommonUtility.GetApiContent(
String.Format(ClientConfiguration.TwilioServiceChatHistory, id, GlobalSettingsDataSource.Current.SelectedProfile, channelName));
if (appResponse.IsSuccessStatusCode)
{
var chatContent = await appResponse.Content.ReadAsStringAsync();
List<ChatMessage> chatMsgs = JsonConvert.DeserializeObject<List<ChatMessage>>(chatContent);
Messages.ReplaceRange(chatMsgs);
}
}
catch
{
// ignore if there are any issues with twilio
}
}
}
}
below is a sample action which is returning HttpResponseMessage and if any error occur then this way web api action returning error message and status code to client side return Request.CreateErrorResponse(HttpStatusCode.NotFound, message);.
[HttpGet, Route("GetAll")]
public HttpResponseMessage GetAllCustomers()
{
IEnumerable<Customer> customers = repository.GetAll();
if (customers == null)
{
var message = string.Format("No customers found");
return Request.CreateErrorResponse(HttpStatusCode.NotFound, message);
}
else
{
return Request.CreateResponse(HttpStatusCode.OK, customers);
}
}
when i am invoking action by http client then i am not getting message in ReasonPhrase property. just tell me what is the right way to read message at client side which is passing like this way return Request.CreateResponse(HttpStatusCode.OK, customers);
here is my client side code
private async void btnFind_Click(object sender, EventArgs e)
{
var fullAddress = baseAddress + "api/customer/GetByID/"+txtFind.Text;
Customer _Customer = null;
using (var client = new HttpClient())
{
using (var response = client.GetAsync(fullAddress).Result)
{
if (response.IsSuccessStatusCode)
{
var customerJsonString = await response.Content.ReadAsStringAsync();
_Customer = JsonConvert.DeserializeObject<Customer>(customerJsonString);
}
else
{
Console.WriteLine("{0} ({1})", (int)response.StatusCode, response.ReasonPhrase);
}
}
}
if (_Customer != null)
{
var _CustList = new List<Customer> { _Customer };
dgCustomers.DataSource = _CustList;
}
}
response.ReasonPhrase not holding the message which i am passing from action. so may be i am not doing things to read message. please tell me what to change in my code to read the message. thanks
i have the job this way.
private async void btnFind_Click(object sender, EventArgs e)
{
var fullAddress = baseAddress + "api/customer/GetByID/"+txtFind.Text;
Customer _Customer = null;
try
{
using (var client = new HttpClient())
{
using (var response = client.GetAsync(fullAddress).Result)
{
if (response.IsSuccessStatusCode)
{
var customerJsonString = await response.Content.ReadAsStringAsync();
_Customer = JsonConvert.DeserializeObject<Customer>(customerJsonString);
}
else
{
//Console.WriteLine("{0} ({1})", (int)response.StatusCode, response.ReasonPhrase);
var ErrMsg = JsonConvert.DeserializeObject<dynamic>(response.Content.ReadAsStringAsync().Result);
MessageBox.Show(ErrMsg.Message);
}
}
}
if (_Customer != null)
{
var _CustList = new List<Customer> { _Customer };
dgCustomers.DataSource = _CustList;
}
}
catch (HttpRequestException ex)
{
// catch any exception here
}
}
read error message this way.
var ErrMsg = JsonConvert.DeserializeObject<dynamic>(response.Content.ReadAsStringAsync().Result);
see my sample web api action which take one string type parameter.
[RoutePrefix("api/customer")]
public class CustomerController : ApiController
{
[HttpPost, Route("DeleteCustomer")]
public HttpResponseMessage DeleteProduct(string customerID)
{
HttpResponseMessage response = null;
Customer customer = repository.Get(customerID);
if (customer == null)
{
var message = string.Format("No customer found by the ID {0}", customerID);
HttpError err = new HttpError(message);
response = Request.CreateErrorResponse(HttpStatusCode.ExpectationFailed, err);
response.ReasonPhrase = message;
}
else
{
if(repository.Remove(customerID))
{
response = Request.CreateResponse<Customer>(HttpStatusCode.Created, customer);
response.ReasonPhrase = "Customer successfully deleted";
}
else
{
var message = string.Format("Due to some error customer not removed");
HttpError err = new HttpError(message);
response = Request.CreateErrorResponse(HttpStatusCode.ExpectationFailed, err);
response.ReasonPhrase = message;
}
}
return response;
}
}
and calling like this below way with http client but not working and giving error Not found
private void btnDelete_Click(object sender, EventArgs e)
{
var uri = new Uri(ConfigurationManager.AppSettings["baseAddress"] + "/api/customer/DeleteCustomer");
var content = new FormUrlEncodedContent(new[]
{
new KeyValuePair<string, string>("customerID", "CUS01")
});
try
{
using (var client = new HttpClient())
{
using (var response = client.PostAsync(uri, content).Result)
{
if (response.IsSuccessStatusCode)
{
MessageBox.Show(response.ReasonPhrase);
}
else
{
Console.WriteLine("{0} ({1})", (int)response.StatusCode, response.ReasonPhrase);
var dict = JsonConvert.DeserializeObject<Dictionary<string, string>>(response.Content.ReadAsStringAsync().Result);
MessageBox.Show(dict["Message"]);
}
}
}
}
catch (HttpRequestException ex)
{
// catch any exception here
}
}
some one please see my code and tell me where i made the mistake in calling code ? thanks
[RoutePrefix("api/customer")]
public class CustomerController : ApiController
{
[HttpPost, Route("DeleteCustomer")]
public HttpResponseMessage DeleteProduct([FromBody]string customerID)
{
HttpResponseMessage response = null;
Customer customer = repository.Get(customerID);
if (customer == null)
{
var message = string.Format("No customer found by the ID {0}", customerID);
HttpError err = new HttpError(message);
response = Request.CreateErrorResponse(HttpStatusCode.ExpectationFailed, err);
response.ReasonPhrase = message;
}
else
{
if(repository.Remove(customerID))
{
response = Request.CreateResponse<Customer>(HttpStatusCode.Created, customer);
response.ReasonPhrase = "Customer successfully deleted";
}
else
{
var message = string.Format("Due to some error customer not removed");
HttpError err = new HttpError(message);
response = Request.CreateErrorResponse(HttpStatusCode.ExpectationFailed, err);
response.ReasonPhrase = message;
}
}
return response;
}
}
Could you add [FromBody] keyword in method parameter ?
I tried to mke a request with GET and parameters. However, I got an exception for the WinPhone8.1 which meaned that GET was a violation protocol due to a content added in. So making a POST request is the solution.
Despite my searches, I'm still not able to set the content lenght property of my HttpWebRequest.. Why?
private static async void AsyncRequest(string url, string contentType, string methodType, int contentLenght, Action<Object, string> callback, Action<HttpStatusCode, JObject, Action<Object, string>> parserFunction)
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
request.ContentType = contentType;
request.Method = methodType;
request.Proxy = null;
if (methodType == Method.POST)
{
request.ContentLenght = "contentLenght";
request.Headers["content-length"] = "contentLenght";
request.Headers["Content-Length"] = "contentLenght";
request.Headers[HttpRequestHeader.ContentLength] = "contentLenght";
request.Headers["HttpRequestHeader.ContentLength"] = "contentLenght";
request.Content.Headers.ContentLength = "contentLenght";
...........
Nothing works ><
}
Debug.WriteLine("1");
Task<WebResponse> task = Task.Factory.FromAsync(
request.BeginGetResponse,
asyncResult => request.EndGetResponse(asyncResult),
(object)null);
Debug.WriteLine("2");
await task.ContinueWith(t => ReadStreamFromResponse(t.Result, callback, parserFunction));
}
Thank to jsonmcgraw for its answer on Xamarin Forums
If you want to make a POST request intead of GET request, then there is the two methods which can make you able to make GET/POST requests.
So, first, an async GET request.
public static async Task<string> MakeGetRequest(string url, string cookie)
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create (url);
request.ContentType = "text/html";
request.Method = "GET";
request.Headers ["Cookie"] = cookie;
var response = await request.GetResponseAsync ();
var respStream = response.GetResponseStream();
respStream.Flush ();
using (StreamReader sr = new StreamReader (respStream)) {
//Need to return this response
string strContent = sr.ReadToEnd ();
respStream = null;
return strContent;
}
}
Sample usage:
public static async Task<MyModel[]> GetInfoAsync(int page, string searchString, string cookie)
{
string url = Constants.url + Constants.Path+
"page=" + page +
"&searchString=" + searchString;
string result = await WebControl.MakeGetRequest (url, cookie);
MyModel[] models = Newtonsoft.Json.JsonConvert.DeserializeObject<MyModel[]> (result);
return models;
}
Next, an async POST request
public static async Task<string> MakePostRequest (string url, string data, string cookie, bool isJson = true)
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create (url);
if (isJson)
request.ContentType = "application/json";
else
request.ContentType = "application/x-www-form-urlencoded";
request.Method = "POST";
request.Headers ["Cookie"] = cookie;
var stream = await request.GetRequestStreamAsync ();
using (var writer = new StreamWriter (stream)) {
writer.Write (data);
writer.Flush ();
writer.Dispose ();
}
var response = await request.GetResponseAsync ();
var respStream = response.GetResponseStream();
using (StreamReader sr = new StreamReader (respStream)) {
//Need to return this response
return sr.ReadToEnd();
}
}
Sample usage:
public static async Task<ResultModel> PostInfoAsync(int id, string cookie)
{
string data = "id=" + id;
//third param means that the content type is not json
string resp = await WebControl.MakePostRequest (Constants.url + Constants.Path, data, cookie, false);
ResultModel model;
try {
model = JsonConvert.DeserializeObject<ResultModel> (resp);
}
catch (Exception) {
model = new ResultModel{ isSuccess = false, Message = resp };
}
return model;
}
In our application we use MvcContrib for generating links with the exception of cross area links where Contrib seems to be not working properly (or we are doing something wrong). In services we have a function that generates a List< ZakladkaModel > which contains url and other properties used in generating tabstrib via custom html helper. That function takes as an argument an id of database object and UrlHelper to help in link creating.
m_service.GenerowanieZakladkiDlaKontrolera_ARCH_Akt(idAktu, new UrlHelper(this.ControllerContext.RequestContext));
Then in the GenerowanieZakladkiDlaKontrolera_ARCH_Akt we have something like this:
model.Add(new ZakladkaModel { Aktywnosc = true, NazwaZakladki = "Akt", Url = "" });
model.Add(new ZakladkaModel { Aktywnosc = true, NazwaZakladki = "Wzmianki", Url = url.Action<Usc.Presentation.Areas.FU_RAU.Controllers.ARCH.ARCH_WzmiankiController>(c => c.Index(idAktu)) });
if (tekstJednolity.StanTekstuJednolitego == "RB" || tekstJednolity.StanTekstuJednolitego == "SW")
{
model.Add(new ZakladkaModel { Aktywnosc = true, NazwaZakladki = "t.j. aktu", Url = url.Action<Usc.Presentation.Areas.FU_RAU.Controllers.ARCH.ARCH_TekstJednolityController>(c => c.Edytuj(tekstJednolity.Id)) });
}
else
{
model.Add(new ZakladkaModel { Aktywnosc = true, NazwaZakladki = "t.j. aktu", Url = url.Action<Usc.Presentation.Areas.FU_RAU.Controllers.ARCH.ARCH_TekstJednolityController>(c => c.Raport(tekstJednolity.Id)) });
}
model.Add(new ZakladkaModel { Aktywnosc = true, NazwaZakladki = "Przypisek 1", Url = url.Action<Usc.Presentation.Areas.FU_RAU.Controllers.ARCH.Przypisek1Controller>(c => c.Index(idAktu)) });
model.Add(new ZakladkaModel { Aktywnosc = true, NazwaZakladki = "Przypisek 2", Url = url.Action<Usc.Presentation.Areas.FU_RAU.Controllers.ARCH.Przypisek2Controller>(c => c.Index(idAktu)) });
model.Add(new ZakladkaModel { Aktywnosc = true, NazwaZakladki = "Przypisek 3", Url = url.Action<Usc.Presentation.Areas.FU_RAU.Controllers.ARCH.Przypisek3Controller>(c => c.Edytuj(idAktu)) });
model.Add(new ZakladkaModel { Aktywnosc = true, NazwaZakladki = "Przypisek 4", Url = url.Action<Usc.Presentation.Areas.FU_RAU.Controllers.ARCH.Przypisek4Controller>(c => c.Edytuj(idAktu)) });
Now the problem is that on some co-workers computers it generates links to actions properly and on some it looks like it takes a ranedom area from our app and tries to make an invalid link. We could use a simple url.Action("action","controler") which works fine on all but we would prefer MvcContrib :). Does anyone have any idea why this occurs? Or can share an alternative?
It seems that LinkBuilder which is used under doesn't use GetVirtualPatchForArea at all which as I read is MVC bug. So i decided to make my own HtmlHelper which uses that method:
public static string ActionArea<TController>(this HtmlHelper urlHelper, Expression<Action<TController>> expression) where TController : Controller
{
RouteValueDictionary routeValues = GetRouteValuesFromExpression(expression);
VirtualPathData vpd = new UrlHelper(urlHelper.ViewContext.RequestContext).RouteCollection.GetVirtualPathForArea(urlHelper.ViewContext.RequestContext, routeValues);
return (vpd == null) ? null : vpd.VirtualPath;
}
public static string ActionArea<TController>(this UrlHelper urlHelper, Expression<Action<TController>> expression) where TController : Controller
{
RouteValueDictionary routeValues = GetRouteValuesFromExpression(expression);
VirtualPathData vpd = urlHelper.RouteCollection.GetVirtualPathForArea(urlHelper.RequestContext, routeValues);
return (vpd == null) ? null : vpd.VirtualPath;
}
public static RouteValueDictionary GetRouteValuesFromExpression<TController>(Expression<Action<TController>> action) where TController : Controller
{
if (action == null)
{
throw new ArgumentNullException("action");
}
MethodCallExpression call = action.Body as MethodCallExpression;
if (call == null)
{
throw new ArgumentException("Akcja nie może być pusta.", "action");
}
string controllerName = typeof(TController).Name;
if (!controllerName.EndsWith("Controller", StringComparison.OrdinalIgnoreCase))
{
throw new ArgumentException("Docelowa klasa nie jest kontrolerem.(Nie kończy się na 'Controller')", "action");
}
controllerName = controllerName.Substring(0, controllerName.Length - "Controller".Length);
if (controllerName.Length == 0)
{
throw new ArgumentException("Nie można przejść do kontrolera.", "action");
}
// TODO: How do we know that this method is even web callable?
// For now, we just let the call itself throw an exception.
string actionName = GetTargetActionName(call.Method);
var rvd = new RouteValueDictionary();
rvd.Add("Controller", controllerName);
rvd.Add("Action", actionName);
var namespaceNazwa = typeof(TController).Namespace;
if(namespaceNazwa.Contains("Areas."))
{
int index = namespaceNazwa.IndexOf('.',namespaceNazwa.IndexOf("Areas."));
string nazwaArea = namespaceNazwa.Substring(namespaceNazwa.IndexOf("Areas.") + 6, index - namespaceNazwa.IndexOf("Areas.") + 1);
if (!String.IsNullOrEmpty(nazwaArea))
{
rvd.Add("Area", nazwaArea);
}
}
//var typ = typeof(TController).GetCustomAttributes(typeof(ActionLinkAreaAttribute), true /* inherit */).FirstOrDefault();
/*ActionLinkAreaAttribute areaAttr = typ as ActionLinkAreaAttribute;
if (areaAttr != null)
{
string areaName = areaAttr.Area;
rvd.Add("Area", areaName);
}*/
AddParameterValuesFromExpressionToDictionary(rvd, call);
return rvd;
}
private static string GetTargetActionName(MethodInfo methodInfo)
{
string methodName = methodInfo.Name;
// do we know this not to be an action?
if (methodInfo.IsDefined(typeof(NonActionAttribute), true /* inherit */))
{
throw new InvalidOperationException(String.Format(CultureInfo.CurrentUICulture,
"Nie można wywoływać metod innych niż akcje.", methodName));
}
// has this been renamed?
ActionNameAttribute nameAttr = methodInfo.GetCustomAttributes(typeof(ActionNameAttribute), true /* inherit */).OfType<ActionNameAttribute>().FirstOrDefault();
if (nameAttr != null)
{
return nameAttr.Name;
}
// targeting an async action?
if (methodInfo.DeclaringType.IsSubclassOf(typeof(AsyncController)))
{
if (methodName.EndsWith("Async", StringComparison.OrdinalIgnoreCase))
{
return methodName.Substring(0, methodName.Length - "Async".Length);
}
if (methodName.EndsWith("Completed", StringComparison.OrdinalIgnoreCase))
{
throw new InvalidOperationException(String.Format(CultureInfo.CurrentUICulture,
"Nie można wywoływać kompletnych metod.", methodName));
}
}
// fallback
return methodName;
}
static void AddParameterValuesFromExpressionToDictionary(RouteValueDictionary rvd, MethodCallExpression call)
{
ParameterInfo[] parameters = call.Method.GetParameters();
if (parameters.Length > 0)
{
for (int i = 0; i < parameters.Length; i++)
{
Expression arg = call.Arguments[i];
object value = null;
ConstantExpression ce = arg as ConstantExpression;
if (ce != null)
{
// If argument is a constant expression, just get the value
value = ce.Value;
}
else
{
value = CachedExpressionCompiler.Evaluate(arg);
}
rvd.Add(parameters[i].Name, value);
}
}
}
Hope this helps people with similiar problems. Some of the code above i got from mvc2-rtm-sources modified to my needs http://aspnet.codeplex.com/releases/view/41742