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
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;
}
}
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.
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();
}
}
}
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;
}
}
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;
}