HttpMapTileDataSource.AdditionalRequestHeaders does not add to the request header - c#

I'm adding request headers with the following code example, and I'm expecting to see the information I've added in the request header.
When I follow and review the request header (Telerik Fiddler 4) I can not see the information I added.
I don't know what's wrong with the code. Can you help me?
Thank you in advance.
private HttpMapTileDataSource _dataSource;
public GmHttpTileDataSourceFactory()
{
_dataSource = new
HttpMapTileDataSource("https://tile.openstreetmap.org/{zoomlevel}/{x}/{y}.png");
_dataSource.AdditionalRequestHeaders.Add("Accept-Language", "en");
_dataSource.AdditionalRequestHeaders.Add("Key", "Value");
_dataSource.AdditionalRequestHeaders.Add("blabla", "blabla");
}

Here is a semi-finished code, perhaps to solve the request header problem you encountered.
public class CustomTileDataSource : CustomMapTileDataSource
{
private string _tileUrl;
public Dictionary<string, string> AdditionalRequestHeaders = new Dictionary<string, string>();
private Dictionary<string, string> DefaultRequestHeaders = new Dictionary<string, string>();
public CustomTileDataSource(string tileUrl)
{
_tileUrl = tileUrl;
DefaultRequestHeaders.Add("Cache-Control", "max-age=0");
DefaultRequestHeaders.Add("Accept-Language", "en-US,en;q=0.9,zh-CN;q=0.8,zh;q=0.7");
DefaultRequestHeaders.Add("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3");
DefaultRequestHeaders.Add("Accept-Encoding", "gzip, deflate, br");
DefaultRequestHeaders.Add("User-Agent", "ozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.10 Safari/537.36 Edg/77.0.235.5");
BitmapRequested += BitmapRequestedHandler;
}
private async void BitmapRequestedHandler(CustomMapTileDataSource sender, MapTileBitmapRequestedEventArgs args)
{
var deferral = args.Request.GetDeferral();
try
{
using (var imgStream = await GetTileAsStreamAsync(args.X, args.Y, args.ZoomLevel))
{
var memStream = imgStream.AsRandomAccessStream();
var decoder = await Windows.Graphics.Imaging.BitmapDecoder.CreateAsync(memStream);
var pixelProvider = await decoder.GetPixelDataAsync(Windows.Graphics.Imaging.BitmapPixelFormat.Rgba8, Windows.Graphics.Imaging.BitmapAlphaMode.Straight, new Windows.Graphics.Imaging.BitmapTransform(), Windows.Graphics.Imaging.ExifOrientationMode.RespectExifOrientation, Windows.Graphics.Imaging.ColorManagementMode.ColorManageToSRgb);
var pixels = pixelProvider.DetachPixelData();
var width = decoder.OrientedPixelWidth;
var height = decoder.OrientedPixelHeight;
Parallel.For(0, height, i =>
{
for (int j = 0; j <= width - 1; j++)
{
// Alpha channel Index (RGBA)
var idx = (i * height + j) * 4 + 3;
}
});
var randomAccessStream = new InMemoryRandomAccessStream();
var outputStream = randomAccessStream.GetOutputStreamAt(0);
var writer = new DataWriter(outputStream);
writer.WriteBytes(pixels);
await writer.StoreAsync();
await writer.FlushAsync();
args.Request.PixelData = RandomAccessStreamReference.CreateFromStream(randomAccessStream);
}
}
catch
{
}
deferral.Complete();
}
private Task<MemoryStream> GetTileAsStreamAsync(int x, int y, int zoom)
{
var tcs = new TaskCompletionSource<MemoryStream>();
var quadkey = TileXYZoomToQuadKey(x, y, zoom);
string url;
url = _tileUrl.Replace("{x}", x.ToString()).Replace("{y}", y.ToString()).Replace("{zoomlevel}", zoom.ToString()).Replace("{quadkey}", quadkey);
var request = WebRequest.Create(url);
foreach (var defaultHeader in DefaultRequestHeaders)
{
request.Headers.Add(defaultHeader.Key, defaultHeader.Value);
}
if (AdditionalRequestHeaders.Count > 0)
{
foreach (var addHeader in AdditionalRequestHeaders)
{
request.Headers.Add(addHeader.Key, addHeader.Value);
}
}
request.BeginGetResponse(async a =>
{
var r = (HttpWebRequest)a.AsyncState;
HttpWebResponse response = (HttpWebResponse)r.EndGetResponse(a);
using (var s = response.GetResponseStream())
{
var ms = new MemoryStream();
await s.CopyToAsync(ms);
ms.Position = 0;
tcs.SetResult(ms);
}
}, request);
return tcs.Task;
}
private string TileXYZoomToQuadKey(int tileX, int tileY, int zoom)
{
var quadKey = new StringBuilder();
for (int i = zoom; i >= 1; i += -1)
{
char digit = '0';
int mask = 1 << (i - 1);
if ((tileX & mask) != 0)
Strings.ChrW(Strings.AscW(digit) + 1);
if ((tileY & mask) != 0)
{
Strings.ChrW(Strings.AscW(digit) + 1);
Strings.ChrW(Strings.AscW(digit) + 1);
}
quadKey.Append(digit);
}
return quadKey.ToString();
}
}
Usage
var dataSource = new CustomTileDataSource("https://tile.openstreetmap.org/{zoomlevel}/{x}/{y}.png");
dataSource.AdditionalRequestHeaders.Add("header_name", "header_value");
// other code
var mySource = new MapTileSource(dataSource);
myMap.TileSources.Add(mySource);
During the test, I also encountered the problem that HttpMapTileDataSource.AdditionalRequestHeaders does not display. I tried to use CustomMapTileDataSource to derive and rewrite the related methods so that it can work normally.
The reason for saying that it is a semi-finished product is that it does not establish a good caching mechanism, and the initial loading time is very long.
Best regards.

Related

C# ClientWebSocket not receiving all packets?

I've built a windows service that subscribes to around 10,000 stock tickers in real-time using ClientWebSocket. If I subscribe to 1,000 tickers I receive all the data points as I should (receiving few hundred messages a second), as soon as I get up to 2,000 tickers I don't seem to be receiving the data I should be, 10,000 (receiving thousands of messages a second) its even worse. I've run comparison reports and it looks like I'm losing up to 60% of the packets. I've talked to polygon (the provider of the real-time data) about this issue and they claim their Socket is a firehose and everything that should go out, goes out, and that none of their other clients are complaining. So the only logical thing here would to be to assume its my code, or some limitation. Maybe it's the Task portion of the Receive method? Maybe window's has a max task limitation and I'm exceeding it.
I've also tested this on a high powered dedicated server with 10gb connection so it doesnt seem to be a connection or hardware limitation.
I've also by passed my BlockingCollection cache and the problem still persisted.
Hopefully one of you has some insight, thank you!
Here's my code:
public static ConcurrentDictionary<string, TradeObj> TradeFeed = new ConcurrentDictionary<string, TradeObj>();
public static ConcurrentDictionary<string, QuoteObj> QuoteFeed = new ConcurrentDictionary<string, QuoteObj>();
public static ConcurrentDictionary<string, AggObj> AggFeed = new ConcurrentDictionary<string, AggObj>();
public static BlockingCollection<byte[]> packets = new BlockingCollection<byte[]>();
private static void Start(string[] args)
{
try
{
Polygon.StartSub();
int HowManyConsumers = 2;
for (int i = 0; i < HowManyConsumers; i++)
{
Task.Factory.StartNew(Polygon.ConsumePackets);
}
} catch(Exception e)
{
Console.WriteLine(e.Message);
}
Console.ReadKey();
}
public static async Task StartSub()
{
do
{
using (var socket = new ClientWebSocket())
try
{
// socket.Options.KeepAliveInterval = TimeSpan.Zero;
var Connection = "wss://socket.polygon.io/stocks";
await socket.ConnectAsync(new Uri(Connection), CancellationToken.None);
Console.WriteLine("Websocket opened to Polygon.");
await Send(socket, "{\"action\":\"auth\",\"params\":\""+ConfigurationManager.AppSettings["PolygonAPIToken"]+"\"}");
List<List<string>> batches = new List<List<string>>();
for (int i = 0; i < FeedCache.Tickers.Count(); i += 500)
{
var tempList = new List<string>();
tempList.AddRange(FeedCache.Tickers.Skip(i).Take(500));
batches.Add(tempList);
}
int bNum = 0;
string[] quoteStrings = new string[batches.Count()];
foreach (var tList in batches)
{
var tQuery = "";
tQuery = tQuery + "T." + string.Join(",T.", tList.ToArray());
tQuery = tQuery + ",A." + string.Join(",A.", tList.ToArray());
tQuery = tQuery + ",Q." + string.Join(",Q.", tList.ToArray());
quoteStrings[bNum] = tQuery;
bNum++;
}
for (int i = 0; i < quoteStrings.Count(); i++)
{
string SubscribeString = "{\"action\":\"subscribe\",\"params\":\"" + quoteStrings[i] + "\"}";
await Send(socket, SubscribeString);
}
await Receive(socket);
}
catch (Exception ex)
{
Console.WriteLine($"ERROR - {ex.Message}");
Console.WriteLine(ex.ToString());
}
} while (true);
}
static async Task Send(ClientWebSocket socket, string data)
{
var segment = new ArraySegment<byte>(Encoding.UTF8.GetBytes(data));
await socket.SendAsync(segment, WebSocketMessageType.Text, true, CancellationToken.None);
}
static async Task Receive(ClientWebSocket socket)
{
do {
WebSocketReceiveResult result;
var buffer = new ArraySegment<byte>(new byte[2000]);
using (var ms = new MemoryStream())
{
do
{
result = await socket.ReceiveAsync(buffer, CancellationToken.None);
ms.Write(buffer.Array, buffer.Offset, result.Count);
} while (!result.EndOfMessage);
if (result.MessageType == WebSocketMessageType.Close)
{
await socket.CloseOutputAsync(WebSocketCloseStatus.NormalClosure, "Closed in server by the client", CancellationToken.None);
Console.WriteLine("Socket disconnecting, trying to reconnect.");
await StartSub();
}
else
{
packets.Add(ms.ToArray());
}
}
} while (true);
}
public static async void ConsumePackets()
{
foreach (var buffer in packets.GetConsumingEnumerable())
{
using (var ms = new MemoryStream(buffer))
{
ms.Seek(0, SeekOrigin.Begin);
using (var reader = new StreamReader(ms, Encoding.UTF8))
{
var data = await reader.ReadToEndAsync();
try
{
var j = JArray.Parse(data);
if (j != null)
{
string id = (string)j[0]["ev"];
switch (id)
{
case "T":
AddOrUpdateTrade((string)j[0]["sym"], j);
break;
case "Q":
AddOrUpdateQuote((string)j[0]["sym"], j);
break;
case "A":
AddOrUpdateAgg((string)j[0]["sym"], j);
break;
}
}
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
}
}
}
public static void AddOrUpdateTrade(string ticker, JArray data)
{
TradeFeed.AddOrUpdate(ticker, new TradeObj {
LastPrice = (double)data[0]["p"],
TradeCount = 1
}, (key, existingVal) =>
{
return new TradeObj {
LastPrice = (double)data[0]["p"],
TradeCount = existingVal.TradeCount + 1,
PriceDirection = (double)data[0]["p"] < existingVal.LastPrice ? "D" : "U"
};
});
}
public static void AddOrUpdateAgg(string ticker, JArray data)
{
AggFeed.AddOrUpdate(ticker, new AggObj
{
TickVolume = (long)data[0]["v"],
VolumeShare = (long)data[0]["av"],
OpenPrice = (double)data[0]["op"],
TickAverage = (double)data[0]["a"],
VWAP = (double)data[0]["vw"],
TickClosePrice = (double)data[0]["c"],
TickHighPrice = (double)data[0]["h"],
TickLowPrice = (double)data[0]["l"],
TickOpenPrice = (double)data[0]["o"]
}, (key, existingVal) =>
{
return new AggObj
{
TickVolume = (long)data[0]["v"],
VolumeShare = (long)data[0]["av"],
OpenPrice = (double)data[0]["op"],
TickAverage = (double)data[0]["a"],
VWAP = (double)data[0]["vw"],
TickClosePrice = (double)data[0]["c"],
TickHighPrice = (double)data[0]["h"],
TickLowPrice = (double)data[0]["l"],
TickOpenPrice = (double)data[0]["o"]
};
});
}
public static void AddOrUpdateQuote(string ticker, JArray data)
{
QuoteFeed.AddOrUpdate(ticker, new QuoteObj
{
BidPrice = (double)data[0]["bp"],
BidSize = (double)data[0]["bs"],
AskPrice = (double)data[0]["ap"],
AskSize = (double)data[0]["as"]
}, (key, existingVal) =>
{
return new QuoteObj
{
BidPrice = (double)data[0]["bp"],
BidSize = (double)data[0]["bs"],
AskPrice = (double)data[0]["ap"],
AskSize = (double)data[0]["as"]
};
});
}

Combine the multiple API responses in to one JSON object C#

I am calling the Sharepoint REST API from the C# application multiple times becaues of pagination and it cannot return more the 5000 records at a time. I am calling the API through the loop like
for (int i = 0; i < 10000; i = i + 5000)
{
SP_StrainCodes = "GetByTitle('S%20Codes')/items?$skiptoken=Paged=TRUE%26p_ID=" + i + "&$top=1";
core_URL = BaseURL_SP + SP_StrainCodes;
using (var client_sharePoint = new HttpClient(handler))
{
var response = client_sharePoint.GetAsync(core_URL).Result;
var responsedata = await response.Content.ReadAsStringAsync();
returnObj = JsonConvert.DeserializeObject<SharepointDTO.RootObject>(responsedata);
if (returnObj.d.Next == null)
continue;
}
}
return returnObj;
}
How do I combine the the returnObj from 1st call and the 2nd Call and return as one Object
Something like this :
List<SharepointDTO.RootObject> results = new List<SharepointDTO.RootObject>();
for (int i = 0; i < 10000; i = i + 5000)
{
SP_StrainCodes = "GetByTitle('S%20Codes')/items?$skiptoken=Paged=TRUE%26p_ID=" + i + "&$top=1";
core_URL = BaseURL_SP + SP_StrainCodes;
using (var client_sharePoint = new HttpClient(handler))
{
var response = client_sharePoint.GetAsync(core_URL).Result;
var responsedata = await response.Content.ReadAsStringAsync();
returnObj = JsonConvert.DeserializeObject<SharepointDTO.RootObject>(responsedata);
if (returnObj.d.Next == null)
continue;
}
results.Add(returnObj);
}
return results;

Get Progress To Angular 4 from Async C# Method

it tries to upload excel file from angular to the c# async method and read it
and return the progress to angular until it finishes but it's not working
but it keeps stop in first return
any way to fix it and return my pertc to angular HTTP post
my c# code is
[HttpPost("[action]")]
public async Task<IActionResult> UploadFiles(IFormFile files)
{
string hresult = "done";
string message = "uploaded Successfully";
try
{
Stream stream = files.OpenReadStream();
var binaryReader = new BinaryReader(stream);
var fileContent = binaryReader.ReadBytes((int)files.Length);
MemoryStream ms = new MemoryStream(fileContent);
using (ExcelPackage package = new ExcelPackage(ms))
{
StringBuilder sb = new StringBuilder();
ExcelWorksheet worksheet = package.Workbook.Worksheets[1];
int rowCount = worksheet.Dimension.Rows;
int ColCount = worksheet.Dimension.Columns;
bool bHeaderRow = true;
int tempCount = 0;
for (int row = 1; row <= rowCount; row++)
{
for (int col = 1; col <= ColCount; col++)
{
if (bHeaderRow)
{
sb.Append(worksheet.Cells[row, col].Value.ToString() + "\t");
}
else
{
sb.Append(worksheet.Cells[row, col].Value.ToString() + "\t");
}
var pertc = tempCount * 100 / rowCount;
tempCount++;
var progresult = new ObjectResult(pertc)
{
StatusCode = (int)HttpStatusCode.OK
};
Request.HttpContext.Response.Headers.Add("X-Total-Count", "Working");
return progresult;
}
sb.Append(Environment.NewLine);
}
}
}
catch (Exception ex)
{
hresult = ex.Message;
}
var result = new ObjectResult(message)
{
StatusCode = (int)HttpStatusCode.OK
};
Request.HttpContext.Response.Headers.Add("X-Total-Count", hresult);
return result;
}
and I call it from angular like this
const fileBrowser = this.fileInput.nativeElement;
if (fileBrowser.files && fileBrowser.files[0]) {
const formData = new FormData();
formData.append('files', fileBrowser.files[0]);
this.http.post('/api/Main/UploadFiles', formData)
.subscribe(
res => {
console.log(res);
},
err => {
console.log("Error occured");
}
);
any way to get the percentage from async c# method to get it in angular
It's not possible with HTTP calls, as they allow only one response per request and the server does not know about any clients.
If you want your angular app to actively receive messages from a server than you have to use WebSockets on both the front-end and your back-end. There are several tutorials showing angular services which provide simple solutions, unfortunally can't say much about C# site.
Else you could poll (HTTP GET) the current status of process in an interval, which is of cause not perfecly accurate but probably the easiest solution.
Use OkObjectResult Ok method in this way return Ok(progresult);
For example:
[HttpPost("[action]")]
public async Task<IActionResult> UploadFiles(IFormFile files)
{
string hresult = "done";
string message = "uploaded Successfully";
try
{
Stream stream = files.OpenReadStream();
var binaryReader = new BinaryReader(stream);
var fileContent = binaryReader.ReadBytes((int)files.Length);
MemoryStream ms = new MemoryStream(fileContent);
using (ExcelPackage package = new ExcelPackage(ms))
{
StringBuilder sb = new StringBuilder();
ExcelWorksheet worksheet = package.Workbook.Worksheets[1];
int rowCount = worksheet.Dimension.Rows;
int ColCount = worksheet.Dimension.Columns;
bool bHeaderRow = true;
int tempCount = 0;
for (int row = 1; row <= rowCount; row++)
{
for (int col = 1; col <= ColCount; col++)
{
if (bHeaderRow)
{
sb.Append(worksheet.Cells[row, col].Value.ToString() + "\t");
}
else
{
sb.Append(worksheet.Cells[row, col].Value.ToString() + "\t");
}
var pertc = tempCount * 100 / rowCount;
tempCount++;
var progresult = new ObjectResult(pertc)
{
StatusCode = (int)HttpStatusCode.OK
};
Request.HttpContext.Response.Headers.Add("X-Total-Count", "Working");
return Ok(progresult);
}
sb.Append(Environment.NewLine);
}
}
}
catch (Exception ex)
{
hresult = ex.Message;
}
var result = new ObjectResult(message)
{
StatusCode = (int)HttpStatusCode.OK
};
Request.HttpContext.Response.Headers.Add("X-Total-Count", hresult);
return Ok(result);
}
On Angular .ts file:
this.http.post('/api/Main/UploadFiles', formData)
.map((res: Response) =>
{
console.log(res);
})
.catch(error =>
{
console.log("Error occured");
});
}

Bing Speech to Text API - Communicate via websocket in c#

I'm trying to get the Bing Speech API to work in C# via WebSockets. I've looked through the implementation in Javascript here and have been following the protocol instructions here, but I've come up against a complete brick wall. I can't use the existing C# service because I'm running in a Linux container, so I need to use an implementation on .net Core. Annoyingly, the existing service is closed-source!
I can connect to the web socket successfully, but I can't ever get the server to respond to my connection. I'm expecting to receive a turn.start text message from the server, but I get booted off the server as soon as I've sent a few bytes of an audio file. I know the audio file is in the right format because I've got it directly from the C# service sample here.
I feel like I’ve exhausted the options here. The only thing I can think of now is that I’m not sending the audio chunks correctly. Currently, I’m just sending the audio file in consecutive 4096 bytes. I know the first audio message contains the RIFF header which is only 36 bytes, and then I'm just sending this along with the next (4096-36) bytes.
Here is my code in full. You should just be able to run it as a .net core or .net framework console application, and will need an audio file and an API key.
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net.Http;
using System.Net.WebSockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace ConsoleApp3
{
class Program
{
static void Main(string[] args)
{
Task.Run(async () =>
{
var bingService = new BingSpeechToTextService();
var audioFilePath = #"FILEPATH GOES HERE";
var authenticationKey = #"BING AUTHENTICATION KEY GOES HERE";
await bingService.RegisterJob(audioFilePath, authenticationKey);
}).Wait();
}
}
public class BingSpeechToTextService
{
/* #region Private Static Methods */
private static async Task Receiving(ClientWebSocket client)
{
var buffer = new byte[128];
while (true)
{
var result = await client.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None);
var res = Encoding.UTF8.GetString(buffer, 0, result.Count);
if (result.MessageType == WebSocketMessageType.Text)
{
Console.WriteLine(Encoding.UTF8.GetString(buffer, 0, result.Count));
}
else if (result.MessageType == WebSocketMessageType.Close)
{
Console.WriteLine($"Closing ... reason {client.CloseStatusDescription}");
var description = client.CloseStatusDescription;
//await client.CloseOutputAsync(WebSocketCloseStatus.NormalClosure, "", CancellationToken.None);
break;
}
else
{
Console.WriteLine("Other result");
}
}
}
/* #endregion Private Static Methods */
/* #region Public Static Methods */
public static UInt16 ReverseBytes(UInt16 value)
{
return (UInt16)((value & 0xFFU) << 8 | (value & 0xFF00U) >> 8);
}
/* #endregion Public Static Methods */
/* #region Interface: 'Unscrypt.Bing.SpeechToText.Client.Api.IBingSpeechToTextJobService' Methods */
public async Task<int?> RegisterJob(string audioFilePath, string authenticationKeyStr)
{
var authenticationKey = new BingSocketAuthentication(authenticationKeyStr);
var token = authenticationKey.GetAccessToken();
/* #region Connect web socket */
var cws = new ClientWebSocket();
var connectionId = Guid.NewGuid().ToString("N");
var lang = "en-US";
cws.Options.SetRequestHeader("X-ConnectionId", connectionId);
cws.Options.SetRequestHeader("Authorization", "Bearer " + token);
Console.WriteLine("Connecting to web socket.");
var url = $"wss://speech.platform.bing.com/speech/recognition/interactive/cognitiveservices/v1?format=simple&language={lang}";
await cws.ConnectAsync(new Uri(url), new CancellationToken());
Console.WriteLine("Connected.");
/* #endregion*/
/* #region Receiving */
var receiving = Receiving(cws);
/* #endregion*/
/* #region Sending */
var sending = Task.Run(async () =>
{
/* #region Send speech.config */
dynamic speechConfig =
new
{
context = new
{
system = new
{
version = "1.0.00000"
},
os = new
{
platform = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.115 Safari/537.36",
name = "Browser",
version = ""
},
device = new
{
manufacturer = "SpeechSample",
model = "SpeechSample",
version = "1.0.00000"
}
}
};
var requestId = Guid.NewGuid().ToString("N");
var speechConfigJson = JsonConvert.SerializeObject(speechConfig, Formatting.None);
StringBuilder outputBuilder = new StringBuilder();
outputBuilder.Append("path:speech.config\r\n"); //Should this be \r\n
outputBuilder.Append($"x-timestamp:{DateTime.UtcNow.ToString("yyyy-MM-ddTHH:mm:ss.fffK")}\r\n");
outputBuilder.Append($"content-type:application/json\r\n");
outputBuilder.Append("\r\n\r\n");
outputBuilder.Append(speechConfigJson);
var strh = outputBuilder.ToString();
var encoded = Encoding.UTF8.GetBytes(outputBuilder.ToString());
var buffer = new ArraySegment<byte>(encoded, 0, encoded.Length);
if (cws.State != WebSocketState.Open) return;
Console.WriteLine("Sending speech.config");
await cws.SendAsync(buffer, WebSocketMessageType.Text, true, new CancellationToken());
Console.WriteLine("Sent.");
/* #endregion*/
/* #region Send audio parts. */
var fileInfo = new FileInfo(audioFilePath);
var streamReader = fileInfo.OpenRead();
for (int cursor = 0; cursor < fileInfo.Length; cursor++)
{
outputBuilder.Clear();
outputBuilder.Append("path:audio\r\n");
outputBuilder.Append($"x-requestid:{requestId}\r\n");
outputBuilder.Append($"x-timestamp:{DateTime.UtcNow.ToString("yyyy-MM-ddTHH:mm:ss.fffK")}\r\n");
outputBuilder.Append($"content-type:audio/x-wav");
var headerBytes = Encoding.ASCII.GetBytes(outputBuilder.ToString());
var headerbuffer = new ArraySegment<byte>(headerBytes, 0, headerBytes.Length);
var str = "0x" + (headerBytes.Length).ToString("X");
var headerHeadBytes = BitConverter.GetBytes((UInt16)headerBytes.Length);
var isBigEndian = !BitConverter.IsLittleEndian;
var headerHead = !isBigEndian ? new byte[] { headerHeadBytes[1], headerHeadBytes[0] } : new byte[] { headerHeadBytes[0], headerHeadBytes[1] };
//Audio should be pcm 16kHz, 16bps mono
var byteLen = 8192 - headerBytes.Length - 2;
var fbuff = new byte[byteLen];
streamReader.Read(fbuff, 0, byteLen);
var arr = headerHead.Concat(headerBytes).Concat(fbuff).ToArray();
var arrSeg = new ArraySegment<byte>(arr, 0, arr.Length);
Console.WriteLine($"Sending data from {cursor}");
if (cws.State != WebSocketState.Open) return;
cursor += byteLen;
var end = cursor >= fileInfo.Length;
await cws.SendAsync(arrSeg, WebSocketMessageType.Binary, true, new CancellationToken());
Console.WriteLine("Data sent");
var dt = Encoding.ASCII.GetString(arr);
}
await cws.SendAsync(new ArraySegment<byte>(), WebSocketMessageType.Binary, true, new CancellationToken());
streamReader.Dispose();
/* #endregion*/
{
var startWait = DateTime.UtcNow;
while ((DateTime.UtcNow - startWait).TotalSeconds < 30)
{
await Task.Delay(1);
}
if (cws.State != WebSocketState.Open) return;
}
});
/* #endregion*/
/* #region Wait for tasks to complete */
await Task.WhenAll(sending, receiving);
if (sending.IsFaulted)
{
var err = sending.Exception;
throw err;
}
if (receiving.IsFaulted)
{
var err = receiving.Exception;
throw err;
}
/* #endregion*/
return null;
}
/* #endregion Interface: 'Unscrypt.Bing.SpeechToText.Client.Api.IBingSpeechToTextJobService' Methods */
public class BingSocketAuthentication
{
public static readonly string FetchTokenUri = "https://api.cognitive.microsoft.com/sts/v1.0";
private string subscriptionKey;
private string token;
private Timer accessTokenRenewer;
//Access token expires every 10 minutes. Renew it every 9 minutes.
private const int RefreshTokenDuration = 9;
public BingSocketAuthentication(string subscriptionKey)
{
this.subscriptionKey = subscriptionKey;
this.token = FetchToken(FetchTokenUri, subscriptionKey).Result;
// renew the token on set duration.
accessTokenRenewer = new Timer(new TimerCallback(OnTokenExpiredCallback),
this,
TimeSpan.FromMinutes(RefreshTokenDuration),
TimeSpan.FromMilliseconds(-1));
}
public string GetAccessToken()
{
return this.token;
}
private void RenewAccessToken()
{
this.token = FetchToken(FetchTokenUri, this.subscriptionKey).Result;
Console.WriteLine("Renewed token.");
}
private void OnTokenExpiredCallback(object stateInfo)
{
try
{
RenewAccessToken();
}
catch (Exception ex)
{
Console.WriteLine(string.Format("Failed renewing access token. Details: {0}", ex.Message));
}
finally
{
try
{
accessTokenRenewer.Change(TimeSpan.FromMinutes(RefreshTokenDuration), TimeSpan.FromMilliseconds(-1));
}
catch (Exception ex)
{
Console.WriteLine(string.Format("Failed to reschedule the timer to renew access token. Details: {0}", ex.Message));
}
}
}
private async Task<string> FetchToken(string fetchUri, string subscriptionKey)
{
using (var client = new HttpClient())
{
client.DefaultRequestHeaders.Add("Ocp-Apim-Subscription-Key", subscriptionKey);
UriBuilder uriBuilder = new UriBuilder(fetchUri);
uriBuilder.Path += "/issueToken";
var result = await client.PostAsync(uriBuilder.Uri.AbsoluteUri, null);
Console.WriteLine("Token Uri: {0}", uriBuilder.Uri.AbsoluteUri);
return await result.Content.ReadAsStringAsync();
}
}
}
}
}
I knew it was going to be simple.
After a frustrating few hours of coding, I've found the problem. I've been forgetting to send a request id along with the speech.config call.

How to pause/resume jobs with Quartz.Net

I have 8 jobs in my project. They start in the Application_Start event and repeat forever. Two of them are using the same class. One job every 7 seconds and the other job every 30 seconds working. But they use the same method at 1 point. Reading a date from an xml file.
If the date is older than the current date, it changes the session id and adds 20 minutes to it. The session id is constantly changing as both are trying to enter and process at the same time.
The following is my need:
1 - Enter the method.
2 - If the session is to be changed, stop the tasks other than the current task.
3 - Change session and save to xml.
4 - Restart or resume all my passive tasks.
private DateTimeOffset g_canlimacgetir = DateTimeOffset.UtcNow.AddSeconds(0);
private DateTimeOffset g_canliorangetir = DateTimeOffset.UtcNow.AddSeconds(45);
private void CanliOranlariGetir()
{
try
{
ISchedulerFactory schfack = new StdSchedulerFactory();
IScheduler scheduler = schfack.GetScheduler();
IJobDetail jobdetay = JobBuilder.Create<CanliOranlar>()
.WithIdentity("canliorangetir")
.Build();
ITrigger trigger = TriggerBuilder.Create()
.WithSimpleSchedule(s => s.WithIntervalInSeconds(7).RepeatForever()).StartAt(g_canliorangetir).Build();
scheduler.ScheduleJob(jobdetay, trigger);
scheduler.Start();
}
}
private void CanliMaclariGetir()
{
try
{
ISchedulerFactory schfack = new StdSchedulerFactory();
IScheduler scheduler = schfack.GetScheduler();
IJobDetail jobdetay = JobBuilder.Create<CanliMaclar>()
.WithIdentity("canlimacgetir")
.Build();
ITrigger trigger = TriggerBuilder.Create()
.WithSimpleSchedule(s => s.WithIntervalInSeconds(30).RepeatForever()).StartAt(g_canlimacgetir).Build();
scheduler.ScheduleJob(jobdetay, trigger);
scheduler.Start();
}
}
private Headers GetTheToken()
{
Headers h = new Headers();
HttpWebResponse response = null;
try
{
const string session_site = "";
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(session_site);
Uri uri = new Uri("");
request.Method = "GET";
request.UserAgent = "Mozilla/5.0 (Windows NT 10.0; WOW64; rv:50.0) Gecko/20100101 Firefox/50.0";
request.Accept = "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8";
request.ContentType = "text/html; charset=utf-8";
request.ContentLength = 0;
Cookie trackerID = new Cookie("trackerId", ConfigurationManager.AppSettings["TrackerID"].ToString()) { Domain = uri.Host };
DateTime tarih = DateTime.Now;
request.Timeout = 5000;
ServicePointManager.Expect100Continue = false;
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
ServicePointManager.ServerCertificateValidationCallback = new
RemoteCertificateValidationCallback(delegate { return true; });
response = (HttpWebResponse)request.GetResponse();
StreamReader reader = new StreamReader(response.GetResponseStream(), Encoding.UTF8);
response.Close();
response.Dispose();
reader.Close();
reader.Dispose();
DateTime sesstimeout = DateTime.Now.AddSeconds(1199);
string getCookieHeader = response.Headers[HttpResponseHeader.SetCookie];
char[] ayiricilar = { '=', ',', ';' };
string[] parcalar = getCookieHeader.Split(ayiricilar);
int ses = 0, rv = 0, xt = 0, xct = 0;
if (parcalar.Length > 20)
{
h.session_timeout = sesstimeout;
for (int i = 0; i < parcalar.Length; i++)
{
if (parcalar[i] == "ASP.NET_SessionId") { h.sessionID = parcalar[i + 1]; ses = 1; }
else if (parcalar[i] == "__RequestVerificationToken") { h.request_verification = parcalar[i + 1]; rv = 1; }
else if (parcalar[i] == "XSRF-TOKEN") { h.xsrf_token = parcalar[i + 1]; xt = 1; }
else if (parcalar[i] == "XSRF-COOKIE-TOKEN") { h.xsrf_cookie_token = parcalar[i + 1]; xct = 1; }
if (ses == 1 && rv == 1 && xt == 1 && xct == 1) i = parcalar.Length;
}
}
response.Close();
response.Dispose();
XmlDocument doc = new XmlDocument();
XmlReader xmlReader = new XmlTextReader(HostingEnvironment.MapPath("~/xml/values.xml"));
doc.Load(xmlReader);
xmlReader.Close();
XmlNodeList InfoNode = doc.SelectNodes("SessionInfo/Info");
InfoNode[0].Attributes["SessionExpires"].Value = h.session_timeout.ToString();
InfoNode[0].Attributes["SessionID"].Value = h.sessionID;
InfoNode[0].Attributes["XSRF-TOKEN"].Value = h.xsrf_token;
InfoNode[0].Attributes["XSRF-COOKIE-TOKEN"].Value = h.xsrf_cookie_token;
InfoNode[0].Attributes["_requestVerification"].Value = h.request_verification.ToString();
doc.Save(HostingEnvironment.MapPath("~/xml/values.xml"));
}
return h;
}
For all jobs you can use
scheduler.PauseAll();
scheduler.ResumeAll();
But if you want to stop and start a specific job you can use this:
scheduler.PauseJob(jobdetay.Key);
scheduler.ResumeJob(jobdetay.Key);

Categories