I am working with an application that will call OData Service. I tried the Simple.OData.Client but I can't get it working..
Here is the code that I try
var client = new ODataClient("http://packages.nuget.org/v1/FeedService.svc/");
var packages = await client.FindEntriesAsync("Packages?$filter=Title eq 'Simple.OData.Client'");
foreach (var package in packages)
{
Console.WriteLine(package["Title"]);
}
I get this error
Error 1 The 'await' operator can only be used within an async method. Consider marking this method with the 'async' modifier and changing its return type to 'Task'.
using System;
using Simple.OData.Client;
namespace ODataClient
{
class Program
{
static void Main(string[] args)
{
new Manager().GetData();
Console.ReadLine();
}
}
}
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
namespace ODataClient
{
public class Manager
{
private readonly Simple.OData.Client.ODataClient client;
public Manager()
{
client = new Simple.OData.Client.ODataClient("http://packages.nuget.org/v1/FeedService.svc/");
}
public void GetData()
{
try
{
IEnumerable<IDictionary<string, object>> response = GetPackages().Result;
foreach (var package in response)
{
Console.WriteLine(package["Title"]);
}
}
catch (Exception e)
{
Console.WriteLine(e);
}
}
private async Task<IEnumerable<IDictionary<string, object>>> GetPackages()
{
var packages = await client.FindEntriesAsync("Packages?$filter=Title eq 'Simple.OData.Client'");
return packages;
}
}
}
This is even simpler. We need SimpleQuery method, since we cannot add the async keyword to the Main or any entry point methods.
static async void SimpleQuery()
{
var client = new ODataClient("http://blahb...lah.svc/");
try
{
var packages = await client.FindEntriesAsync("Products");
foreach (var package in packages)
{
Console.WriteLine(package);
}
} catch (Exception e)
{
Console.WriteLine("Simple Query " + e);
}
}
static void Main(string[] args)
{
Console.WriteLine("Press Enter when the job is completed");
SimpleQuery();
Console.ReadLine();
}
Related
I am implementing webhook using asp.net core 3.1 webhook package. This is a custom webhook poc and I need to expose this webhook to external users. During runtime I am facing below error and unable to solve it.
What can I try next?
Error:
Unable to find WebHook filters for the 'jr4o27tr2r472' receiver. Add the required configuration by calling a receiver-specific method that calls 'Microsoft.Extensions.DependencyInjection.IMvcBuilder.AddWebHooks' or 'IMvcCoreBuilder.AddWebHooks' in the application startup code. For example, call 'IMvcCoreBuilder.AddGitHubWebHooks' to configure a minimal GitHub receiver.
When I hit this url (http://localhost:49846/api/webhooks/incoming/jr4o27tr2r472/teleported), I am getting this issue in eventviewer.
Note: I have added required webhook services as part of configurationservice method.
public static class UnicornServiceCollectionSetup
{
public static void AddUnicornServices(IServiceCollection services)
{
WebHookMetadata.Register<UnicornMetadata>(services);
services.AddSingleton<UnicornSignatureFilter>();
}
}
public static class UnicornMvcCoreBuilderExtensions
{
public static IMvcCoreBuilder AddUnicornWebHooks(this IMvcCoreBuilder builder)
{
UnicornServiceCollectionSetup.AddUnicornServices(builder.Services);
return builder.AddWebHooks();
}
}
public class UnicornMetadata : WebHookMetadata, IWebHookFilterMetadata
{
private readonly UnicornSignatureFilter _verifySignatureFilter;
public UnicornMetadata(UnicornSignatureFilter verifySignatureFilter)
: base(UnicornConstants.ReceiverName)
{
_verifySignatureFilter = verifySignatureFilter;
}
public override WebHookBodyType BodyType => WebHookBodyType.Json;
public void AddFilters(WebHookFilterMetadataContext context)
{
context.Results.Add(_verifySignatureFilter);
}
}
public class UnicornSignatureFilter : WebHookVerifySignatureFilter,
IAsyncResourceFilter
{
private readonly byte[] _secret;
public UnicornSignatureFilter(//IOptions<UnicornConfig> options,
IConfiguration configuration,
IHostingEnvironment hostingEnvironment,
ILoggerFactory loggerFactory)
: base(configuration, hostingEnvironment, loggerFactory)
{
//_secret = Encoding.UTF8.GetBytes(options.Value.SharedSecret);
_secret = Encoding.UTF8.GetBytes("secret");
}
public override string ReceiverName => UnicornConstants.ReceiverName;
public async Task OnResourceExecutionAsync(ResourceExecutingContext context,
ResourceExecutionDelegate next)
{
if (context == null) throw new ArgumentNullException(nameof(context));
if (next == null) throw new ArgumentNullException(nameof(next));
var request = context.HttpContext.Request;
if (!HttpMethods.IsPost(request.Method))
{
await next();
return;
}
var errorResult = EnsureSecureConnection(ReceiverName, request);
if (errorResult != null)
{
context.Result = errorResult;
return;
}
var header = GetRequestHeader(request,
UnicornConstants.SignatureHeaderName,
out errorResult);
if (errorResult != null)
{
context.Result = errorResult;
return;
}
byte[] payload;
using (var ms = new MemoryStream())
{
HttpRequestRewindExtensions.EnableBuffering(request);
await request.Body.CopyToAsync(ms);
payload = ms.ToArray();
request.Body.Position = 0;
}
if (payload == null || payload.Length == 0)
{
context.Result = new BadRequestObjectResult("No payload");
return;
}
var digest = FromBase64(header, UnicornConstants.SignatureHeaderName);
var secretPlusJson = _secret.Concat(payload).ToArray();
using (var sha512 = new SHA512Managed())
{
if (!SecretEqual(sha512.ComputeHash(secretPlusJson), digest))
{
context.Result =
new BadRequestObjectResult("Signature verification failed");
return;
}
}
await next();
}
}
Note: I am attaching source code in this webhookpoc.
I have been working on a device which is sending some data to an Azure IoT hub
The device is doing this on two different locations in the code. On one side it works perfectly and I can connect to the Hub via Connection String and transport type MQTT_WebSocket_Only.
public static class Mqtt2IoTNew
{
private static string _DeviceConnectionString = Properties.Settings.Default.MqttUri;
private static TransportType _TransportType = TransportType.Mqtt_WebSocket_Only;
public static void Send(object argEntry, bool argIsList)
{
var deviceClient = DeviceClient.CreateFromConnectionString(_DeviceConnectionString, _TransportType);
deviceClient.ReceiveAsync(TimeSpan.FromSeconds(2)).Wait();
var message = new Message(deviceClient, argEntry, argIsList);
message.RunAsync().GetAwaiter().GetResult();
}
}
internal class Message
{
private DeviceClient _DeviceClient;
private readonly string _Message;
public Message(DeviceClient argDeviceClient, object argEntry, bool isList)
{
_DeviceClient = argDeviceClient;
StringBuilder stb = new StringBuilder();
if (isList)
{
foreach (var entity in (List<object>) argEntry)
{
stb.Append("<entity>").Append(JsonConvert.SerializeObject(entity)).Append("</entity>\n");
}
}
else
{
stb.Append(JsonConvert.SerializeObject(argEntry));
}
_Message = stb.ToString();
}
public async Task RunAsync()
{
await SendEvent().ConfigureAwait(false);
}
private async Task SendEvent()
{
Microsoft.Azure.Devices.Client.Message eventMessage = new Microsoft.Azure.Devices.Client.Message(Encoding.UTF8.GetBytes(_Message));
await _DeviceClient.SendEventAsync(eventMessage).ConfigureAwait(false);
}
}
//Call of method that does not work
protected override void DoOnCompleted(IRepository argRepository)
{
if (_CurrentlySendingTreadId.HasValue)
{
if (_CurrentlySendingTreadId.Value == Thread.CurrentThread.ManagedThreadId)
{
return;
}
}
TaskFactoryProvider.GetFactory().StartNew(()=>SendBatchProtocols());
}
public bool SendBatchProtocols()
{
using (var repository = RepositoryProviderHolder.RepositoryProvider.GetRepository(Constants.CONTAINERCONTRACT_PRODUCTIONREPOSITORY))
{
IQueryable<BatchProtocol> batchProtocolQuery = repository.GetQuery<BatchProtocol>().OrderBy(bp => bp.InternalNoInteger);
batchProtocolQuery = batchProtocolQuery.Where(bp => !bp.IsArchived).Take(1);
if (!batchProtocolQuery.Any()) return false;
var batchProtocols = batchProtocolQuery.ToList();
IsBatchProtocolSend = false;
try
{
foreach (var bps in batchProtocols)
{
Mqtt2IoTNew.Send(bps,false);
}
IsBatchProtocolSend = true;
}
catch (Exception ex)
{
throw;
}
}
return IsBatchProtocolSend;
}
//Call of Method that does work
private void AddEntitiesAndSaveChanges(IEnumerable argEntities)
{
if (argEntities == null)
{
return;
}
lock (_UnderlyingRepositoryAccessLockObject)
{
#region Log2DornerIoT
if (Properties.Settings.Default.Log2DornerIoT)
{
List<object> entities = new List<object>();
int i = 0;
foreach (var entity in argEntities)
{
if (i < 100)
{
entities.Add(entity);
i++;
}
else
{
try
{
Mqtt2IoTNew.Send(entities, true);
}
catch (Exception e)
{
throw;
}
entities.Clear();
i = 0;
}
}
}
}
on the other part of the code, I am only colling the same class to use to send method in the same way but here I get an exception which says "TLS authentication error" and the inner exception "Unable to connect to the remote server", "The underlying connection was closed: Could not establish trust relationship for the SSL/TLS secure channel".
But: I never used any kind of authorization not in the first part which works perfectly neither in the second.
I would be very happy if someone could help me. I have found nothing so fare regarding this issue.
Thanks for your time.
Michael
I found the reason why it didn't work. There was a Persmissice Certificate Policy applied that blocked the certificate at one side of the project. I disabled it and now it works perfectly fine.
Thanks for the help anyway.
I need help with creating a windows service using Threading and asynchronous HttpWebRequest calls. I have created a few C# windows services before but never using threading. Also, I seem to be getting hung up with the async calls using HttpWebRequest. I have googled this as well as looking on this site. I could not find anything that helped. This is mainly because I could not seem to get what was presented in other questions to work in my specific example.
Please keep in mind that I may be overlapping things based on my lack of knowledge in this specific area as well as through trying to figure it out.
The main flow of this is to get a list of urls during onStart. Typically this list would be retrieved from a _facade.GetUrls call. Then, at each time interval call scanSites. A request is made to each url and then I save the results to the database in _facade.SaveUrlResponse.
My problems is it seems as if I am caught in an endless loop when I debug it. I am not exactly sure how/where to do this. Thanks in advance.
Here is what I have:
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Net;
using System.ServiceProcess;
using System.Threading;
using URLValidation.BusinessManager.Facade;
using URLValidation.BusinessManager.Model;
namespace URLValidation
{
partial class URLValidation : ServiceBase
{
#region " class variables "
private System.Timers.Timer _timer;
private List<UrlModel> _url_List = null;
private Facade _facade;
private Thread _t;
private int _x;
#endregion
public URLValidation()
{
_facade = new Facade();
InitializeComponent();
}
protected override void OnStart(string[] args)
{
try
{
_url_List = new List<UrlModel>
{
new UrlModel(address: "http://www.google.com", addressID: 1),
new UrlModel(address: "http://www.microsoft.com", addressID: 2),
new UrlModel(address: "http://www.stackoverflow.com", addressID: 3)
};
resetTimer();
GC.KeepAlive(_timer);
}
catch (Exception ex)
{
throw ex;
}
}
private void resetTimer()
{
try
{
_timer = new System.Timers.Timer();
_timer.Interval = 10000;//1800000; //30 minutes
_timer.Start();
_timer.Enabled = true;
_timer.Elapsed += scanSites;
}
catch (Exception ex)
{
throw ex;
}
}
private void scanSites(object sender, System.Timers.ElapsedEventArgs e)
{
_timer.Stop();
_x = 0;
_t = new Thread(new ThreadStart(scanSites));
_t.IsBackground = true;
_t.Start();
}
private void scanSites()
{
try
{
foreach (UrlModel url in _url_List)
{
_x += 1;
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url.Address);
request.Method = "HEAD";
RequestModel requestModel = new RequestModel(request, url);
IAsyncResult result = request.BeginGetResponse(new AsyncCallback(saveUrlResponse), requestModel);
ThreadPool.RegisterWaitForSingleObject
(
result.AsyncWaitHandle,
new WaitOrTimerCallback(ScanTimeoutCallback),
requestModel,
(30 * 1000), // 30 second timeout
true
);
}
}
catch (Exception ex)
{
throw ex;
}
}
private void saveUrlResponse(IAsyncResult result)
{
//grab the custom state object
RequestModel requestModel = (RequestModel)result.AsyncState;
HttpWebRequest request = (HttpWebRequest)requestModel.Request;
//get the Response
HttpWebResponse response = (HttpWebResponse)request.EndGetResponse(result);
// process the response...
ResponseModel responseModel = new ResponseModel(request, response, requestModel.UrlModel.AddressID);
_facade.SaveUrlResponse(responseModel);
}
private void ScanTimeoutCallback(object requestModel, bool timedOut)
{
if (timedOut)
{
RequestModel reqState = (RequestModel)requestModel;
if (reqState != null)
reqState.Request.Abort();
}
if (_x == _url_List.Count)
{
resetTimer();
}
}
protected override void OnStop()
{
// TODO: Add code here to perform any tear-down necessary to stop your service.
}
}
}
Okay, I think I am getting somewhere. I have moved my code to a console app. I am able to get the results saved to the database by using either GetResponse (sync) and BeginGetResponse (async). From what I can tell I believe this is a good solution. Can somebody verify this and let me know if you foresee any problems once this is moved to a Windows Service. Here is the new code
using System;
using System.Collections.Generic;
using System.Net;
using System.Threading;
namespace ConsoleApplication2
{
static class Program
{
private static List<UrlModel> _url_List = null;
private static Object _acctLock = new object();
private static Facade _facade = new Facade();
static void Main(string[] args)
{
_url_List = new List<UrlModel>
{
new UrlModel(address: "http://www.microsoft.com", addressID: 1),
new UrlModel(address: "http://www.google.com", addressID: 2),
new UrlModel(address: "http://www.stackoverflow.com", addressID: 3)
};
lockThreadAndGetUrlStatus(_url_List);
Console.ReadLine();
}
static void lockThreadAndGetUrlStatus(List<UrlModel> _url_List)
{
Thread[] threads;
try
{
threads = new Thread[_url_List.Count];
Thread.CurrentThread.Name = "main";
int i = 0;
foreach (UrlModel url in _url_List)
{
//Thread t = new Thread(() => scanSites(url));
Thread t = new Thread(() => scanSitesWithAsync(url));
t.Name = i.ToString();
threads[i] = t;
i += 1;
}
for (i = 0; i < _url_List.Count; i++)
{
Console.WriteLine("Thread {0} Alive : {1}", threads[i].Name, threads[i].IsAlive);
threads[i].Start();
Console.WriteLine("Thread {0} Alive : {1}", threads[i].Name, threads[i].IsAlive);
}
Console.WriteLine("Current Priority : {0}", Thread.CurrentThread.Priority);
Console.WriteLine("Thread {0} Ending", Thread.CurrentThread.Name);
}
catch (Exception ex)
{
throw ex;
}
}
static void scanSitesWithAsync(UrlModel url)
{
try
{
lock (_acctLock)
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url.Address);
request.Method = "HEAD";
RequestModel requestModel = new RequestModel(request, url);
IAsyncResult result = request.BeginGetResponse(new AsyncCallback(saveUrlResponseWithAsync), requestModel);
ThreadPool.RegisterWaitForSingleObject
(
result.AsyncWaitHandle,
new WaitOrTimerCallback(scanTimeoutCallback),
requestModel, 30000, true
);
}
}
catch (Exception ex)
{
throw ex;
}
}
static void saveUrlResponseWithAsync(IAsyncResult result)
{
try
{
RequestModel requestModel = (RequestModel)result.AsyncState;
HttpWebRequest request = (HttpWebRequest)requestModel.Request;
//get the Response
HttpWebResponse response = (HttpWebResponse)request.EndGetResponse(result);
// process the response...
ResponseModel responseModel = new ResponseModel(requestModel.Request, response, requestModel.UrlModel.AddressID);
_facade.SaveUrlResponse(responseModel);
Console.WriteLine(response.StatusCode);
}
catch (Exception ex)
{
throw ex;
}
}
static void scanTimeoutCallback(object requestModel, bool timedOut)
{
try
{
if (timedOut)
{
RequestModel reqState = (RequestModel)requestModel;
if (reqState != null)
reqState.Request.Abort();
}
}
catch (Exception ex)
{
throw ex;
}
}
}
}
looks like you are trying to issue 3 async requests at the same time. By default, the HTTP/1.1 protocol only specifies 2 connections
I have this base class structure:
Base:
public abstract class BackgroundTask
{
protected readonly Logger Logger = LogManager.GetCurrentClassLogger();
protected virtual void Initialize()
{
// initialize database access
}
public void Run()
{
Initialize();
try
{
Execute();
// insert to database or whatever
}
catch (Exception ex)
{
Logger.ErrorException(string.Format("Error proccesing task: {0}\r\n", ToString()), ex);
Exceptions.Add(ex);
}
finally
{
TaskExecuter.Discard();
}
}
protected abstract void Execute();
public abstract override string ToString();
public IList<Exception> Exceptions = new List<Exception>();
}
Task executor:
public static class TaskExecuter
{
private static readonly ThreadLocal<IList<BackgroundTask>> TasksToExecute
= new ThreadLocal<IList<BackgroundTask>>(() => new List<BackgroundTask>());
public static void ExecuteLater(BackgroundTask task)
{
TasksToExecute.Value.Add(task);
}
public static void StartExecuting()
{
foreach (var backgroundTask in TasksToExecute.Value)
{
Task.Factory.StartNew(backgroundTask.Run);
}
}
public static void Discard()
{
TasksToExecute.Value.Clear();
TasksToExecute.Dispose();
}
}
FileTask:
public class FileTask : BackgroundTask
{
protected static string BaseFolder = #"C:\ASCII\";
private static readonly ReaderWriterLockSlim Lock = new ReaderWriterLockSlim();
private readonly string _folder;
private IHistoryRepository _historyRepository;
public string Folder
{
get { return _folder; }
}
public FileTask(string folder)
{
_folder = string.Format("{0}{1}", BaseFolder, folder);
}
protected override void Initialize()
{
_historyRepository = new HistoryRepository();
}
protected override void Execute()
{
// todo: Get institute that are active,
var institute = MockInstitute(); // todo: uncomment _historyRepository.FindInstituteByFolderName(Folder);
// todo: Update institute, lastupdate - [date] | [files amount] | [phonenumbers amount]
if (institute == null)
{
Logger.Warn("Not found data", Folder);
return;
}
// todo: read file get encoding | type and parse it
Task.Factory.StartNew(ReadFile);
}
private void ReadFile()
{
var list = GetFilesByFolder();
StreamReader sr = null;
try
{
Lock.EnterReadLock();
foreach (var fi in list)
{
var fileName = fi.FullName;
Logger.Info("Line: {0}:=> Content: {1}", fileName, Thread.CurrentThread.ManagedThreadId);
sr = new StreamReader(fileName, DetectEncoding(fileName));
string currentLine;
while ((currentLine = sr.ReadLine()).ReturnSuccess())
{
if (string.IsNullOrEmpty(currentLine)) continue;
Logger.Info("Line: {0}:=> Content: {1}", fileName, currentLine);
}
}
Lock.ExitReadLock();
}
finally
{
if (sr != null) sr.Dispose();
Logger.Info("Finished working" + Folder);
}
}
protected IEnumerable<FileInfo> GetFilesByFolder()
{
return Directory.GetFiles(Folder).Select(fileName => new FileInfo(fileName));
}
protected Encoding DetectEncoding(string file)
{
using (FileStream fs = new FileStream(file, FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite))
{
var cdet = new Ude.CharsetDetector();
cdet.Feed(fs);
cdet.DataEnd();
return cdet.With(x => x.Charset)
.Return(x => Encoding.GetEncoding(cdet.Charset),
Encoding.GetEncoding("windows-1255"));
}
}
private Institute MockInstitute()
{
return new Institute
{
FromFolderLocation = string.Format("{0}{1}", BaseFolder, Folder)
};
}
public override string ToString()
{
return string.Format("Folder: {0}", Folder);
}
}
When don't read the file every thing ok, the Log is populated and every thing runs smooth,
but when i attach the Task.Factory.StartNew(ReadFile); method i have an exception.
Exception:
Cannot access a disposed object.
Object name: 'The ThreadLocal object has been disposed.'.
How do i solve that issue? might i need to change the LocalThread logic, or what - i have been trying to handle that issue, for almost a day.
BTW: It's an MVC4 project, and C# 5.0 and i'm trying to TDD it all.
You shouldn't be calling TasksToExecute.Dispose();
there.
I'm trying to find a clean way to accomplish MvvmLight's IDataService pattern with async/await.
Originally I was using the callback Action method to work similar to the template's but that doesn't update the UI either.
public interface IDataService
{
void GetData(Action<DataItem, Exception> callback);
void GetLocationAsync(Action<Geoposition, Exception> callback);
}
public class DataService : IDataService
{
public void GetData(Action<DataItem, Exception> callback)
{
// Use this to connect to the actual data service
var item = new DataItem("Location App");
callback(item, null);
}
public async void GetLocationAsync(Action<Geoposition, Exception> callback)
{
Windows.Devices.Geolocation.Geolocator locator = new Windows.Devices.Geolocation.Geolocator();
var location = await locator.GetGeopositionAsync();
callback(location, null);
}
}
public class MainViewModel : ViewModelBase
{
private readonly IDataService _dataService;
private string _locationString = string.Empty;
public string LocationString
{
get
{
return _locationString;
}
set
{
if (_locationString == value)
{
return;
}
_locationString = value;
RaisePropertyChanged(LocationString);
}
}
/// <summary>
/// Initializes a new instance of the MainViewModel class.
/// </summary>
public MainViewModel(IDataService dataService)
{
_dataService = dataService;
_dataService.GetLocation(
(location, error) =>
{
LocationString = string.Format("({0}, {1})",
location.Coordinate.Latitude,
location.Coordinate.Longitude);
});
}
}
I'm trying to databind against gps coordinates but since the async fires and doesn't run on main thread it doesn't update the UI.
Might be unrelated, but AFAICT you're missing some quotes
RaisePropertyChanged(LocationString);
You pass the name of the property that changed, not its value.