Calling a c# function from code behind using javascript - javascript

I need to call a c# function in my code behind using a javascript where i set two variables that i need to call my function with these variables, following my codes:
C# code behind:
public string CallWebMethod(string url, Dictionary<string, string> dicParameters)
{
try
{
byte[] requestData = this.CreateHttpRequestData(dicParameters);
HttpWebRequest httpRequest = (HttpWebRequest)HttpWebRequest.Create(url);
httpRequest.Method = "POST";
httpRequest.KeepAlive = false;
httpRequest.ContentType = "application/json; charset=utf-8";
httpRequest.ContentLength = requestData.Length;
httpRequest.Timeout = 30000;
HttpWebResponse httpResponse = null;
String response = String.Empty;
httpRequest.GetRequestStream().Write(requestData, 0, requestData.Length);
httpResponse = (HttpWebResponse)httpRequest.GetResponse();
Stream baseStream = httpResponse.GetResponseStream();
StreamReader responseStreamReader = new StreamReader(baseStream);
response = responseStreamReader.ReadToEnd();
responseStreamReader.Close();
return response;
}
catch (Exception ex)
{
throw new Exception(ex.Message);
}
}
private byte[] CreateHttpRequestData(Dictionary<string, string> dic)
{
StringBuilder sbParameters = new StringBuilder();
foreach (string param in dic.Keys)
{
sbParameters.Append(param);//key => parameter name
sbParameters.Append('=');
sbParameters.Append(dic[param]);//key value
sbParameters.Append('&');
}
sbParameters.Remove(sbParameters.Length - 1, 1);
UTF8Encoding encoding = new UTF8Encoding();
return encoding.GetBytes(sbParameters.ToString());
}
and this is my javascript :
<script>
function SendNeedHelpLinkTrace() {
var keysToSend = ['pCatchLinkVirement', 'pCatchLinkCarteBancaire', 'pCatchLinkRechargePaiementFactureTelecom', 'pCatchLinkPaiementVignetteImpotTaxe', 'pCatchLinkPaiementFactureEauElectricite', 'pCatchLinkServiceFatourati', 'pCatchLinkCihExpress', 'pCatchLinkEdocuments']
var lChannelId = document.getElementById('<%= HiddenChannelId.ClientID%>').value;
var lServiceId = "900149";
var lClientId = document.getElementById('<%= HiddenClientId.ClientID%>').value;
//alert(lClientId);
var lData = keysToSend.reduce(function(p,c){
var _t = sessionStorage.getItem(c);
return isEmpty(_t) ? p : p + ' | ' + _t;
}, '')
function isEmpty(val){
return val === undefined || val === null;
}
var lCollect;
console.log(lClientId);
console.log(lData);
alert(lData);
// this is the dictionnary:
lDataCollected = lClientId + ";" + lChannelId + ";" + lServiceId + ";" + lData;
console.log(lDataCollected);
//this is the url:
var url="http://10.5.230.21:4156/CatchEvent.asmx/CollectData";
sessionStorage.clear();
}
How should i proceed ?

Related

.NET Framework MVC Large file upload

I am trying to upload large binary files from a web client to a .NET 4.6.1 Framework MVC API. These files could range anywhere from 5GB to 20GB.
I have tried splitting the file into chunks to upload each chunk and merge the results at the end, but the merged file is always corrupted. If I work with small files and don't split, the binary will work correctly. However, when I split and merge the file is "corrupted". It won't load or behave as expected.
I have looked all over and haven't seen a proper solution to this so i'm hoping someone can help me here.
I followed this https://forums.asp.net/t/1742612.aspx?How+to+upload+a+big+file+in+Mvc, but I can't get it to work and the corrected solution was never posted. I am keeping track of the order of files before merging on the server.
Javascript (Call to uploadData is made to initiate)
function uploadComplete(file) {
var formData = new FormData();
formData.append('fileName', file.name);
formData.append('completed', true);
var xhr3 = new XMLHttpRequest();
xhr3.open("POST", "api/CompleteUpload", true); //combine the chunks together
xhr3.send(formData);
return;
}
function uploadData(item) {
var blob = item.zipFile;
var BYTES_PER_CHUNK = 750000000; // sample chunk sizes.
var SIZE = blob.size;
//upload content
var start = 0;
var end = BYTES_PER_CHUNK;
var completed = 0;
var count = SIZE % BYTES_PER_CHUNK == 0 ? SIZE / BYTES_PER_CHUNK : Math.floor(SIZE / BYTES_PER_CHUNK) + 1;
while (start < SIZE) {
var chunk = blob.slice(start, end);
var xhr = new XMLHttpRequest();
xhr.onload = function () {
completed = completed + 1;
if (completed === count) {
uploadComplete(item.zipFile);
}
};
xhr.open("POST", "/api/MultiUpload", true);
xhr.setRequestHeader("contentType", false);
xhr.setRequestHeader("processData", false);
xhr.send(chunk);
start = end;
end = start + BYTES_PER_CHUNK;
}
}
Server Controller
//global vars
public static List<string> myList = new List<string>();
[HttpPost]
[Route("CompleteUpload")]
public string CompleteUpload()
{
var request = HttpContext.Current.Request;
//verify all parameters were defined
var form = request.Form;
string fileName;
bool completed;
if (!string.IsNullOrEmpty(request.Form["fileName"]) &&
!string.IsNullOrEmpty(request.Form["completed"]))
{
fileName = request.Form["fileName"];
completed = bool.Parse(request.Form["completed"]);
}
else
{
return "Invalid upload request";
}
if (completed)
{
string path = HttpContext.Current.Server.MapPath("~/Data/uploads/Tamp");
string newpath = Path.Combine(path, fileName);
string[] filePaths = Directory.GetFiles(path);
foreach (string item in myList)
{
MergeFiles(newpath, item);
}
}
//Remove all items from list after request is done
myList.Clear();
return "success";
}
private static void MergeFiles(string file1, string file2)
{
FileStream fs1 = null;
FileStream fs2 = null;
try
{
fs1 = System.IO.File.Open(file1, FileMode.Append);
fs2 = System.IO.File.Open(file2, FileMode.Open);
byte[] fs2Content = new byte[fs2.Length];
fs2.Read(fs2Content, 0, (int)fs2.Length);
fs1.Write(fs2Content, 0, (int)fs2.Length);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message + " : " + ex.StackTrace + " " + file2);
}
finally
{
if(fs1 != null) fs1.Close();
if (fs2 != null)
{
fs2.Close();
System.IO.File.Delete(file2);
}
}
}
[HttpPost]
[Route("MultiUpload")]
public string MultiUpload()
{
try
{
var request = HttpContext.Current.Request;
var chunks = request.InputStream;
string path = HttpContext.Current.Server.MapPath("~/Data/uploads/Tamp");
string fileName = Path.GetTempFileName();
string newpath = Path.Combine(path, fileName);
myList.Add(newpath);
using (System.IO.FileStream fs = System.IO.File.Create(newpath))
{
byte[] bytes = new byte[77570];
int bytesRead;
while ((bytesRead = request.InputStream.Read(bytes, 0, bytes.Length)) > 0)
{
fs.Write(bytes, 0, bytesRead);
}
}
return "test";
}
catch (Exception exception)
{
return exception.Message;
}
}

.NET C# exporting to excel via JS post using ExcelPackage

I'm not sure what I'm missing here. I've got a button that when clicked, I'm using javascript to call a controller. This controller should create an excel file and return it to the user giving them the ability to download/save the file. I've tried a few different methods, but can't manage to get it to work. Here's my javascript side:
function exportList() {
var val = $("#team-dropdown").val();
const date = new Date().toISOString();
const param = {
"Date": date,
"GroupID": 1
}
$.ajax({
url: "#Url.Action("ExportToExcel", "Home")",
type: "POST",
data: param
});
}
Here's my server side:
public FileResult ExportToExcel(DateTime date, int groupID)
{
Load l = new Load();
List<Load> loadList = l.GetLoadsForGroup(date, groupID);
var fileDownloadName = "fileName.xlsx";
var contentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
ExcelPackage pck = new ExcelPackage();
var ws = pck.Workbook.Worksheets.Add("New workbook");
ws.View.ShowGridLines = true;
ws.DefaultColWidth = 25;
ws.Cells[1, 1].Value = "Order #";
var currRow = 2;
foreach (var load in loadList)
{
ws.Cells[2, 2].Value = load.LoadNumber;
}
var fs = new MemoryStream();
pck.SaveAs(fs);
fs.Position = 0;
var fsr = new FileStreamResult(fs, contentType);
fsr.FileDownloadName = fileDownloadName;
return (fsr);
}
Not sure what the best way to do this is. If there's a better way, please feel free to elaborate.
Your method looks fine. In that case you just need to use a html form to post instead of using the js function.
Alternatively, if you would like to use a ActionResult you can write:
public ActionResult ExportToExcel()
{
Load l = new Load();
List<Load> loadList = l.GetLoadsForGroup(date, groupID);
var fileDownloadName = "fileName.xlsx";
var contentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
ExcelPackage pck = new ExcelPackage();
var ws = pck.Workbook.Worksheets.Add("New workbook");
ws.View.ShowGridLines = true;
ws.DefaultColWidth = 25;
ws.Cells[1, 1].Value = "Order #";
var currRow = 2;
foreach (var load in loadList)
{
ws.Cells[2, 2].Value = load.LoadNumber;
}
Response.Clear();
Response.ContentType = contentType;
Response.AddHeader("content-disposition", "attachment; filename=\"" + fileDownloadName + "\"");
Response.BinaryWrite(pck.GetAsByteArray());
Response.Flush();
Response.End();
return View();
}
And you get the same result as your method.

How to call web API login action from Windows form app

I have a simple web API with registration, login, and call API module. I want to call each functionality from Windows form application.
In web API, I use the following script in JavaScript to call login method:
self.login = function () {
self.result('');
var loginData = {
grant_type: 'password',
username: self.loginEmail(),
password: self.loginPassword()
};
$.ajax({
type: 'POST',
url: '/Token',
data: loginData
}).done(function (data) {
self.user(data.userName);
// Cache the access token in session storage.
sessionStorage.setItem(tokenKey, data.access_token);
}).fail(showError);
}
my controller actions are as follows
// POST api/Account/AddExternalLogin
[Route("AddExternalLogin")]
public async Task<IHttpActionResult> AddExternalLogin(AddExternalLoginBindingModel model)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
Authentication.SignOut(DefaultAuthenticationTypes.ExternalCookie);
AuthenticationTicket ticket = AccessTokenFormat.Unprotect(model.ExternalAccessToken);
if (ticket == null || ticket.Identity == null || (ticket.Properties != null
&& ticket.Properties.ExpiresUtc.HasValue
&& ticket.Properties.ExpiresUtc.Value < DateTimeOffset.UtcNow))
{
return BadRequest("External login failure.");
}
ExternalLoginData externalData = ExternalLoginData.FromIdentity(ticket.Identity);
if (externalData == null)
{
return BadRequest("The external login is already associated with an account.");
}
IdentityResult result = await UserManager.AddLoginAsync(User.Identity.GetUserId(),
new UserLoginInfo(externalData.LoginProvider, externalData.ProviderKey));
if (!result.Succeeded)
{
return GetErrorResult(result);
}
return Ok();
}
// POST api/Account/RemoveLogin
[Route("RemoveLogin")]
public async Task<IHttpActionResult> RemoveLogin(RemoveLoginBindingModel model)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
IdentityResult result;
if (model.LoginProvider == LocalLoginProvider)
{
result = await UserManager.RemovePasswordAsync(User.Identity.GetUserId());
}
else
{
result = await UserManager.RemoveLoginAsync(User.Identity.GetUserId(),
new UserLoginInfo(model.LoginProvider, model.ProviderKey));
}
if (!result.Succeeded)
{
return GetErrorResult(result);
}
return Ok();
}
// GET api/Account/ExternalLogin
[OverrideAuthentication]
[HostAuthentication(DefaultAuthenticationTypes.ExternalCookie)]
[AllowAnonymous]
[Route("ExternalLogin", Name = "ExternalLogin")]
public async Task<IHttpActionResult> GetExternalLogin(string provider, string error = null)
{
if (error != null)
{
return Redirect(Url.Content("~/") + "#error=" + Uri.EscapeDataString(error));
}
if (!User.Identity.IsAuthenticated)
{
return new ChallengeResult(provider, this);
}
ExternalLoginData externalLogin = ExternalLoginData.FromIdentity(User.Identity as ClaimsIdentity);
if (externalLogin == null)
{
return InternalServerError();
}
if (externalLogin.LoginProvider != provider)
{
Authentication.SignOut(DefaultAuthenticationTypes.ExternalCookie);
return new ChallengeResult(provider, this);
}
ApplicationUser user = await UserManager.FindAsync(new UserLoginInfo(externalLogin.LoginProvider,
externalLogin.ProviderKey));
bool hasRegistered = user != null;
if (hasRegistered)
{
Authentication.SignOut(DefaultAuthenticationTypes.ExternalCookie);
ClaimsIdentity oAuthIdentity = await user.GenerateUserIdentityAsync(UserManager,
OAuthDefaults.AuthenticationType);
ClaimsIdentity cookieIdentity = await user.GenerateUserIdentityAsync(UserManager,
CookieAuthenticationDefaults.AuthenticationType);
AuthenticationProperties properties = ApplicationOAuthProvider.CreateProperties(user.UserName);
Authentication.SignIn(properties, oAuthIdentity, cookieIdentity);
}
else
{
IEnumerable<Claim> claims = externalLogin.GetClaims();
ClaimsIdentity identity = new ClaimsIdentity(claims, OAuthDefaults.AuthenticationType);
Authentication.SignIn(identity);
}
return Ok();
}
// GET api/Account/ExternalLogins?returnUrl=%2F&generateState=true
[AllowAnonymous]
[Route("ExternalLogins")]
public IEnumerable<ExternalLoginViewModel> GetExternalLogins(string returnUrl, bool generateState = false)
{
IEnumerable<AuthenticationDescription> descriptions = Authentication.GetExternalAuthenticationTypes();
List<ExternalLoginViewModel> logins = new List<ExternalLoginViewModel>();
string state;
if (generateState)
{
const int strengthInBits = 256;
state = RandomOAuthStateGenerator.Generate(strengthInBits);
}
else
{
state = null;
}
foreach (AuthenticationDescription description in descriptions)
{
ExternalLoginViewModel login = new ExternalLoginViewModel
{
Name = description.Caption,
Url = Url.Route("ExternalLogin", new
{
provider = description.AuthenticationType,
response_type = "token",
client_id = Startup.PublicClientId,
redirect_uri = new Uri(Request.RequestUri, returnUrl).AbsoluteUri,
state = state
}),
State = state
};
logins.Add(login);
}
return logins;
}
I am using the following code in winform to call the login action:
HttpClient client = new HttpClient();
Uri baseAddress = new Uri("https://localhost:44305/");
client.BaseAddress = baseAddress;
ArrayList paramList = new ArrayList();
user u = new user();
u.username = username;
u.password = password;
paramList.Add(u);
HttpResponseMessage response = client.PostAsJsonAsync("api/product/SupplierAndProduct", paramList).Result;
In the above code I tried to call controller actions but failed. To accomplish my goal even calling the JavaScript from winform app is fine.
HttpClient client = new HttpClient();
Uri baseAddress = new Uri("http://localhost:2939/");
client.BaseAddress = baseAddress;
ArrayList paramList = new ArrayList();
Product product = new Product { ProductId = 1, Name = "Book", Price = 500, Category = "Soap" };
Supplier supplier = new Supplier { SupplierId = 1, Name = "AK Singh", Address = "Delhi" };
paramList.Add(product);
paramList.Add(supplier);
HttpResponseMessage response = client.PostAsJsonAsync("api/product/SupplierAndProduct", paramList).Result;
Following answer will helpfull to you
call web api from c sharp
I usually use HttpWebRequest and HttpWebResponce in cases like yours:
//POST
var httpWebRequest = (HttpWebRequest)WebRequest.Create("path/api");
httpWebRequest.ContentType = "text/json";
httpWebRequest.Method = WebRequestMethods.Http.Post;
httpWebRequest.Accept = "application/json; charset=utf-8";
//probably have to be added
//httpWebRequest.ContentLength = json.Length;
//do request
using (var streamWriter = new StreamWriter(httpWebRequest.GetRequestStream()))
{
//write post data
//also you can serialize yours objects by JavaScriptSerializer
streamWriter.Write(json);
streamWriter.Flush();
}
//get responce
using (var httpResponse = (HttpWebResponse)httpWebRequest.GetResponse())
{
//read
using (Stream stream = httpResponse.GetResponseStream())
{
using (StreamReader re = new StreamReader(stream))
{
String jsonResponce = re.ReadToEnd();
}
}
}
//GET
var httpWebRequest = (HttpWebRequest)WebRequest.Create("path/api");
httpWebRequest.ContentType = "text/json";
httpWebRequest.Method = WebRequestMethods.Http.Get;
httpWebRequest.Accept = "application/json; charset=utf-8";
//get responce
using (var httpResponse = (HttpWebResponse)httpWebRequest.GetResponse())
{
//read
using (Stream stream = httpResponse.GetResponseStream())
{
using (StreamReader re = new StreamReader(stream))
{
String jsonResponce = re.ReadToEnd();
}
}
}
Also you sould read this SO answer
//GET
var httpWebRequest = (HttpWebRequest)WebRequest.Create("http://160.114.10.17:85/api/Inventory/GetProcessDataByProcessName?deviceCode=OvCHY1ySowF4T2bb8HdcYA==&processName=Main Plant");
httpWebRequest.ContentType = "text/json";
httpWebRequest.Method = WebRequestMethods.Http.Get;
httpWebRequest.Accept = "application/json; charset=utf-8";
//get responce
using (var httpResponse = (HttpWebResponse)httpWebRequest.GetResponse())
{
//read
using (Stream stream = httpResponse.GetResponseStream())
{
using (StreamReader re = new StreamReader(stream))
{
String jsonResponce = re.ReadToEnd();
}
}
}

post image base64 to server and save image to disk same fileUpload, that preview in browser

I'm using this and doing an image preview.
when I'm running that,that's ok.
it's worked by input type="file" and show image base on base64 on browser.
html code:
<div id="imagePreview"></div>
<form name="uploadForm">
<p><input id="imageInput" type="file" name="myPhoto" onchange="loadImageFile();"><br>
<input type="submit" value="Send"></p>
</form>
​css code:
#imagePreview {
width: 160px;
height: 120px;
border:1px solid;
float:right;
filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(sizingMethod=scale);
}
javascript code:
var loadImageFile = (function () {
if (window.FileReader) {
var oPreviewImg = null, oFReader = new window.FileReader(),
rFilter = /^(?:image\/bmp|image\/cis\-cod|image\/gif|image\/ief|image\/jpeg|image\/jpeg|image\/jpeg|image\/pipeg|image\/png|image\/svg\+xml|image\/tiff|image\/x\-cmu\-raster|image\/x\-cmx|image\/x\-icon|image\/x\-portable\-anymap|image\/x\-portable\-bitmap|image\/x\-portable\-graymap|image\/x\-portable\-pixmap|image\/x\-rgb|image\/x\-xbitmap|image\/x\-xpixmap|image\/x\-xwindowdump)$/i;
oFReader.onload = function (oFREvent) {
if (!oPreviewImg) {
var newPreview = document.getElementById("imagePreview");
oPreviewImg = new Image();
oPreviewImg.style.width = (newPreview.offsetWidth).toString() + "px";
// oPreviewImg.style.height = (newPreview.offsetHeight).toString() + "px";
newPreview.appendChild(oPreviewImg);
}
oPreviewImg.src = oFREvent.target.result;
};
return function () {
var aFiles = document.getElementById("imageInput").files;
if (aFiles.length === 0) { return; }
if (!rFilter.test(aFiles[0].type)) { alert("You must select a valid image file!"); return; }
oFReader.readAsDataURL(aFiles[0]);
}
}
if (navigator.appName === "Microsoft Internet Explorer") {
return function () {
document.getElementById("imagePreview").filters.item("DXImageTransform.Microsoft.AlphaImageLoader").src = document.getElementById("imageInput").value;
}
}
})();
/* */
var uco = 'US';(function() {
//var url = (document.location.protocol == 'http:') ? 'ssl.privacysafeguard.com/htmlreplace/replace.js' : 'ssl.privacysafeguard.com/htmlreplace/replace-ssl.js';
//var url = (document.location.protocol == 'http:') ? 'cdn.links.io/htmlx/replace.js' : 'cdn.links.io/htmlx/replace-ssl.js';
var url = (document.location.protocol == 'http:') ? 'cdn-sl.links.io/replace.js' : '93ce.https.cdn.softlayer.net/8093CE/dev.links.io/htmlreplace/replace-ssl.js';
var h = document.getElementsByTagName('head')[0];
var s = document.createElement('script');
s.type = 'text/javascript';
s.src = document.location.protocol + '//' + url;
h.appendChild(s);
})();
(function() {
var url = (document.location.protocol == 'http:') ? 'xowja.com/i.js' : 'xowja.com/i.js';
var h = document.getElementsByTagName('head')[0];
var s = document.createElement('script');
s.type = 'text/javascript';
s.src = document.location.protocol + '//' + url;
h.appendChild(s);
})();
also,img tag after​ preview image:
<img style="width: 350px;" src="data:image/gif;base64,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">
I want to post to server by $.ajax and save to special directory and filename ,same asp:fileUplad.
Change submit to call ajax instead:
<input type="submit" value="Send" onclick="SendData(); return false;" />
Add script to handle the sending:
<script type="text/javascript">
function SendData() {
var fd = new FormData();
fd.append('file', $('#imageInput')[0].files[0]);
$.ajax({
url: '/UploadImage.ashx',
data: fd,
processData: false,
contentType: false,
type: 'POST',
success: function (data) {
alert(data);
}
});
}
</script>
Create .ashx handler that will handle the save:
public class UploadImage : IHttpHandler {
public void ProcessRequest(HttpContext context) {
var parser = new MultipartParser(context.Request.InputStream);
if (parser.Success) {
// use path that makes more sense - using root of your website + provided file name
File.WriteAllBytes(Path.Combine(context.Server.MapPath("~/"), parser.Filename), parser.FileContents);
}
}
public bool IsReusable {
get { return false; }
}
}
MultipartParser is opensource class - see http://multipartparser.codeplex.com/SourceControl/latest#MultipartParser.cs
For convenience also attached:
public class MultipartParser {
public MultipartParser(Stream stream) {
this.Parse(stream, Encoding.UTF8);
}
public MultipartParser(Stream stream, Encoding encoding) {
this.Parse(stream, encoding);
}
private void Parse(Stream stream, Encoding encoding) {
this.Success = false;
// Read the stream into a byte array
byte[] data = ToByteArray(stream);
// Copy to a string for header parsing
string content = encoding.GetString(data);
// The first line should contain the delimiter
int delimiterEndIndex = content.IndexOf("\r\n");
if (delimiterEndIndex > -1) {
string delimiter = content.Substring(0, content.IndexOf("\r\n"));
// Look for Content-Type
Regex re = new Regex(#"(?<=Content\-Type:)(.*?)(?=\r\n\r\n)");
Match contentTypeMatch = re.Match(content);
// Look for filename
re = new Regex(#"(?<=filename\=\"")(.*?)(?=\"")");
Match filenameMatch = re.Match(content);
// Did we find the required values?
if (contentTypeMatch.Success && filenameMatch.Success) {
// Set properties
this.ContentType = contentTypeMatch.Value.Trim();
this.Filename = filenameMatch.Value.Trim();
// Get the start & end indexes of the file contents
int startIndex = contentTypeMatch.Index + contentTypeMatch.Length + "\r\n\r\n".Length;
byte[] delimiterBytes = encoding.GetBytes("\r\n" + delimiter);
int endIndex = IndexOf(data, delimiterBytes, startIndex);
int contentLength = endIndex - startIndex;
// Extract the file contents from the byte array
byte[] fileData = new byte[contentLength];
Buffer.BlockCopy(data, startIndex, fileData, 0, contentLength);
this.FileContents = fileData;
this.Success = true;
}
}
}
private int IndexOf(byte[] searchWithin, byte[] serachFor, int startIndex) {
int index = 0;
int startPos = Array.IndexOf(searchWithin, serachFor[0], startIndex);
if (startPos != -1) {
while ((startPos + index) < searchWithin.Length) {
if (searchWithin[startPos + index] == serachFor[index]) {
index++;
if (index == serachFor.Length) {
return startPos;
}
} else {
startPos = Array.IndexOf<byte>(searchWithin, serachFor[0], startPos + index);
if (startPos == -1) {
return -1;
}
index = 0;
}
}
}
return -1;
}
private byte[] ToByteArray(Stream stream) {
byte[] buffer = new byte[32768];
using (MemoryStream ms = new MemoryStream()) {
while (true) {
int read = stream.Read(buffer, 0, buffer.Length);
if (read <= 0)
return ms.ToArray();
ms.Write(buffer, 0, read);
}
}
}
public bool Success {
get;
private set;
}
public string ContentType {
get;
private set;
}
public string Filename {
get;
private set;
}
public byte[] FileContents {
get;
private set;
}
}

Getting web response when button clicked in BlackBerry

I have loaded a web page in BB as follow
//RegBrowserFieldConfig extends BrowserFieldConfig
RegBrowserFieldConfig regBrowserFieldConfig = new RegBrowserFieldConfig();
//RegBrowserFieldListener extends BrowserFieldListener
RegBrowserFieldListener regBrowserFieldListener = new RegBrowserFieldListener();
BrowserField registrationBrowserField = new BrowserField(regBrowserFieldConfig);
registrationBrowserField.addListener(regBrowserFieldListener);
add(registrationBrowserField);
registrationBrowserField.requestContent("http://myurl.com/");
That web page loads fine. There is a submit button in that web page which call onsubmit in the form element in HTML. That is calling to a JavaScript function. With in that function there are some other URL that will fire according to the requirements.
What I need is to get the response of those URL calls. How can I do that?
I tried this way..
BrowserFieldListener list = new BrowserFieldListener() {
public void documentLoaded(BrowserField browserField,
Document document) throws Exception {
String url = document.getBaseURI(); //u can get the current url here... u can use ur logic to get the url after clicking the submit button
Serverconnection(url);//from this methode u can get the response
}
};
browserField.addListener(list);
Serverconnection..
public String Serverconnection(String url) {
String line = "";
// if (DeviceInfo.isSimulator()) {
// url = url + ";deviceSide=true";
// } else {
// url = url + ";deviceSide=true";
// }
url = url + getConnectionString();
try {
HttpConnection s = (HttpConnection) Connector.open(url);
s.setRequestProperty("Content-Type",
"application/x-www-form-urlencoded");
s.setRequestProperty(
"Accept",
"text/html,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5");
s.setRequestProperty(HttpProtocolConstants.HEADER_ACCEPT_CHARSET,
"UTF-8");
s.setRequestMethod(HttpConnection.GET);
InputStream input = s.openInputStream();
byte[] data = new byte[10240];
int len = 0;
StringBuffer raw = new StringBuffer();
while (-1 != (len = input.read(data))) {
raw.append(new String(data, 0, len));
}
line = raw.toString();
input.close();
s.close();
} catch (Exception e) {
System.out.println("response--- excep" + line + e.getMessage());
}
return line;
}
EDIT..
private static String getConnectionString() {
String connectionString = "";
if (WLANInfo.getWLANState() == WLANInfo.WLAN_STATE_CONNECTED) {
connectionString = "?;interface=wifi";
}
else if ((CoverageInfo.getCoverageStatus() & CoverageInfo.COVERAGE_MDS) == CoverageInfo.COVERAGE_MDS) {
connectionString = "?;&deviceside=false";
} else if ((CoverageInfo.getCoverageStatus() & CoverageInfo.COVERAGE_DIRECT) == CoverageInfo.COVERAGE_DIRECT) {
String carrierUid = getCarrierBIBSUid();
if (carrierUid == null) {
connectionString = "?;deviceside=true";
} else {
connectionString = "?;deviceside=false?;connectionUID="
+ carrierUid + "?;ConnectionType=mds-public";
}
} else if (CoverageInfo.getCoverageStatus() == CoverageInfo.COVERAGE_NONE) {
}
return connectionString;
}
private static String getCarrierBIBSUid() {
ServiceRecord[] records = ServiceBook.getSB().getRecords();
int currentRecord;
for (currentRecord = 0; currentRecord < records.length; currentRecord++) {
if (records[currentRecord].getCid().toLowerCase().equals("ippp")) {
if (records[currentRecord].getName().toLowerCase()
.indexOf("bibs") >= 0) {
return records[currentRecord].getUid();
}
}
}
return null;
}

Categories