I am trying to access a JSON object in a URL inside the UIWebView. Here is my code for that -
func webView(myWebView: UIWebView, shouldStartLoadWithRequest request: NSURLRequest, navigationType: UIWebViewNavigationType) -> Bool {
let requestUrl:NSURL = request.URL!
let url:String = requestUrl.absoluteString
if url.rangeOfString("token") != nil {
print("exists")
let index = url.rangeOfString("token=", options: .BackwardsSearch)?.endIndex
let tokenValue = url.substringFromIndex(index!)
if let data = tokenValue.dataUsingEncoding(NSUTF8StringEncoding) {
do {
let json: AnyObject? = try NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.AllowFragments) as! NSDictionary
print(json)
} catch {
print("Something went wrong")
}
}
self.tokenField.text = "\(tokenValue)"
}
The 'request URL' is coming from the following JS -
var tokenObj = {"accessToken":"abc123"};
window.location.href = "didtap://LoginButton?token=" + tokenObj;
The problem here is when I am trying to access the JSON Object using Swift, I see the URL coming in as didtap://LoginButton?token=[object%20Object]
Here is also a screenshot of my debugger.
I am looking for the JSON object as is, so I can use the token back in my app where needed.
You can use substring.stringByRemovingPercentEncoding will solve your problem
Related
I am trying to embed a simple Power BI report inside a ASP web (.NET Core) using controllers. I have already get correctly embedToken, embedURL and ReportID, but when i try to call powerbi.embed() to initialize the report i get the following error:
"ncaught TypeError: this.element.getAttribute is not a function
at e.t.getUniqueId (powerbi.min.js:2)
at e.t.populateConfig (powerbi.min.js:2)
at e.t (powerbi.min.js:2)
at new e (powerbi.min.js:5)
at t.embedNew (powerbi.min.js:2)
at t.embedInternal (powerbi.min.js:2)
at t.embed (powerbi.min.js:2)
at Object.<anonymous> (my-extension.js:125)
at u (jquery.min.js:2)
at Object.fireWith [as resolveWith] (jquery.min.js:2)"
I have tried the EmbedToken, embedUrls, and ReportId in Power BI embed Playground and they works fine, but i get that problem in the code. I believe that the problem may reside in the powerbi.js file, but i have also tried with different files, from nugget package and GitHub and I still have the same problem.
I left the code to get the tokens and initialize the Power BI Report below:
JS file to initialize the Report and Call API to get the tokens: Consider MyPanel as a simple pop-up properties panel:
this._button.onClick = (ev) => {
this._enabled = !this._enabled;
this._button.setState(this._enabled ? 0 : 1);
//Execute an action here
//if null, create docking panel
if (this.panel == null) {
this.panel = new MyPanel(this.viewer, this.viewer.container, 'myPanel', 'My Panel');
this.panel.addVisibilityListener((show) => {
this._button.setState(show ? 0 : 1);
});
}
var request = jQuery.ajax({
url: '/api/forge/PBI/url'
});
request.done(function (data) {
console.log(data);
// Read embed application token from textbox
var txtAccessToken = data.accessToken;
// Read embed URL from textbox
var txtEmbedUrl = data.embedUrl;
// Read report Id from textbox
var txtEmbedReportId = data.reportId;
var models = window['powerbi-client'].models;
var permissions = models.Permissions.All;
var config = {
type: 'report',
tokenType: models.TokenType.Embed,
accessToken: txtAccessToken,
embedUrl: txtEmbedUrl,
id: txtEmbedReportId,
permissions: permissions,
settings: {
panes: {
filters: {
visible: true
},
pageNavigation: {
visible: true
}
}
}
};
var div = $('#PowerBIEmbed');
var report = powerbi.embed(div, config);
});
The C# files to get the tokens an respond to API request:
[ApiController]
public class PowerBi : ControllerBase
{
[HttpGet]
[Route("/api/forge/PBI/url")]
public EmbedConfig GetPBIToken()
{
EmbedConfig pBIData = PBICredentials.GetEmbedToken();
return pBIData;
}
}
public class PBICredentials
{
public static EmbedConfig GetEmbedToken()
{
var a = new Configurations();
using (var client = new PowerBIClient(new Uri(Configurations.ApiUrl),
Authentication.GetTokenCredentials()))
{
// Retrieve the selected Report
var Reports = client.Reports.GetReportsInGroup(Configurations.WorkspaceId);
var Report = Reports.Value.FirstOrDefault();
// Generate an embed token to view
var generateTokenRequestParameters = new GenerateTokenRequest(TokenAccessLevel.View);
var tokenResponse = client.Reports.GenerateTokenInGroup(Configurations.WorkspaceId,
Report.Id, generateTokenRequestParameters);
// Populate embed variables (to be passed client-side)
EmbedConfig embed = new EmbedConfig()
{
AccessToken = tokenResponse.Token,
EmbedUrl = Report.EmbedUrl,
ReportId = Report.Id
};
return embed;
}
}
}
public class EmbedConfig
{
[JsonPropertyName("accessToken")]
public string AccessToken { get; set; }
[JsonPropertyName("embedUrl")]
public string EmbedUrl { get; set; }
[JsonPropertyName("reportId")]
public Guid ReportId { get; set; }
}
Consider the authentification file and Configuration as in the Course "Developers in One Day" From Microsoft Power BI: https://www.youtube.com/playlist?list=PL1N57mwBHtN1AGWHnJMhtvJCIG_IlC07D
Any kind of help will be thanked!
Best regards,
Carlos
You are getting the error at below line:
var div = $('#PowerBIEmbed');
You need to get a reference to the first element inside the div array.
Change the above line to:
var div = $('#PowerBIEmbed')[0];
// or
var div = $('#PowerBIEmbed').get(0);
Please find the reference here: https://learn.microsoft.com/javascript/api/overview/powerbi/embed-report#example
I create a WebSocket chat in NET Core. I don`t know how to deserialize real JSON object.
Parse this like a simple string - worked. But this is not what i need.
let Message = `{
login: userName,
text: messageField.value
}`
chat.socket.send(Message);
messageField.value = "";
JS Real code.
chat.sendMessage = function () {
// var message = userName + ": " + messageField.value;
let Message = {
login: userName,
text: messageField.value
}
chat.socket.send(Message);
messageField.value = "";
}
And this is how i deserialize:
private static async Task<string> ReceiveStringAsync(WebSocket socket, CancellationToken ct = default(CancellationToken))
{
var buffer = new ArraySegment<byte>(new byte[8192]);
using (var ms = new MemoryStream())
{
WebSocketReceiveResult result;
do
{
ct.ThrowIfCancellationRequested();
result = await socket.ReceiveAsync(buffer, ct);
ms.Write(buffer.Array, buffer.Offset, result.Count);
}
while (!result.EndOfMessage);
ms.Seek(0, SeekOrigin.Begin);
if (result.MessageType != WebSocketMessageType.Text)
{
return null;
}
// Encoding UTF8: https://tools.ietf.org/html/rfc6455#section-5.6
using (var reader = new StreamReader(ms, Encoding.UTF8))
{
JsonTextReader jsonReader = new JsonTextReader(reader);
var serializer = new JsonSerializer();
Message msg = serializer.Deserialize<Message>(jsonReader);
return await reader.ReadToEndAsync();
returns simple object,
not the one i tried to deserialize.
In debugger its displayed as [object Object].
[JsonObject]
public class Message
{
[JsonProperty("login")]
public string login { get; set; }
[JsonProperty("text")]
public string text { get; set; }
}
EXCEPTION
Newtonsoft.Json.JsonSerializationException: Cannot deserialize the current JSON array (e.g. [1,2,3]) into type 'Metanit.Models.Message' because the type requires a JSON object (e.g. {"name":"value"}) to deserialize correctly.
To fix this error either change the JSON to a JSON object (e.g. {"name":"value"}) or change the deserialized type to an array or a type that implements a collection interface (e.g. ICollection, IList) like List that can be deserialized from a JSON array. JsonArrayAttribute can also be added to the type to force it to deserialize from a JSON array.
Why exception tolds me Cannot deserialize the current JSON array
its not an array!
It is:
let Message = {
login: userName,
text: messageField.value
}
So I have this function on my site:
function appQrHandlerSet(result) {
jQuery(function() {
jQuery('#readed_qr_url').val(result.url);
jQuery(this).getLayerForm('#qr_handler_layer');
});
}
From the iOS app, I have to call this function and pass a JSON to it, how can I achieve that?
I've been trying to make it work for 3 days now, but I gave up because something is not working right.
Thanks in advance!
According to your code, the parameter result should contain the property url. We suppose that the url contains the JSON data you want to pass.
Try the following 2 approaches:
// Approach 1:
func callJS() {
let json = "{ url:\"An url with json?\"}"
let scriptString = "let result=\(json); appQrHandlerSet(result);"
webView?.evaluateJavaScript(scriptString, completionHandler: { (object, error) in
})
}
// Approach 2:
func initWebViewWithJs() {
let config = WKWebViewConfiguration()
config.userContentController = WKUserContentController()
let json = "{ url:\"An url with json?\"}"
let scriptString = "let result=\(json); appQrHandlerSet(result);"
let script = WKUserScript(source: scriptString, injectionTime: WKUserScriptInjectionTime.atDocumentEnd, forMainFrameOnly: true)
config.userContentController.addUserScript(script)
webView = WKWebView(frame: CGRect(x: 0, y: 0, width: 320, height: 400), configuration: config)
}
My Java code should return user login as a String, but on Javascript side I'm receiving a strange Resource object whose numbered attributes each contains one char.
Here is my Java code:
#PostMapping(path = "/account/reset_password/finish", produces = MediaType.TEXT_PLAIN_VALUE)
#Timed
public ResponseEntity<String> finishPasswordReset(#RequestBody KeyAndPasswordVM keyAndPassword) {
if (!checkPasswordLength(keyAndPassword.getNewPassword())) {
return new ResponseEntity<>("Incorrect password", HttpStatus.BAD_REQUEST);
}
return userService.completePasswordReset(keyAndPassword.getNewPassword(), keyAndPassword.getKey()).map(
user -> new ResponseEntity<String>(user.getLogin(), HttpStatus.OK)).orElse(
new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR));
}
Javascript controller code:
Auth.resetPasswordFinish({key: $stateParams.key, newPassword: vm.resetAccount.password}).then(function (userLogin) {
vm.success = 'OK';
console.log("userLogin="+userLogin);
}).catch(function () {
vm.success = null;
vm.error = 'ERROR';
});
The console prints:
userLogin=[object Object]
which is not very interesting.
Inspecting the received object gives:
One can see that each char of the String is a numbered attribute of the Resource object.
Javascript Auth code:
function resetPasswordFinish (keyAndPassword, callback) {
var cb = callback || angular.noop;
return PasswordResetFinish.save(keyAndPassword, function (userLogin) {
return cb(userLogin);
}, function (err) {
return cb(err);
}).$promise;
}
This one is just passing the parameter to the callback function.
Do you know how to receive a plain String instead of this Resource object? I apologize if this is a trivial question.
I know that doing this will work in order to retrieve the user login:
var i = 0;
var userLoginToString = "";
while (typeof userLogin[String(i)] !== 'undefined') {
userLoginToString += String(userLogin[String(i)]);
i += 1;
}
however I don't think that this is the intended way to use this Resource object.
My knowledge of front end it is not so good, and I don't know how to send array of ids to back end which will get all data and will be open it into new page. pls help
there my function:
#has_session_params('tin')
def print_documents(request):
doc_ids = request.POST.getlist('doc_ids[]')
tin = request.session['tin']
params = dict()
template = 'documents/documents_to_print.html'
params['Docs'] = docs
params['pb'] = pb
params['is_pdf'] = request.GET.get('is_pdf', 'false')
params['host'] = request.scheme + "://" + request.META["HTTP_HOST"]
params['url'] = settings.SITE_URL + request.get_full_path()
params['doc_type'] = INVOICE_TYPE
invoice_list = list()
for doc_id in doc_ids:
response = proxy.get_invoice_by_id(invoice_id=doc_id, tin=tin)
if response.status.code != pb.ResponseStatus.OK:
response = proxy.get_invoice_draft_by_id(
invoice_draft_id=doc_id, tin=tin)
invoice_list.append(response.invoice)
params['invoices'] = invoice_list
return render(request, template, params)
I know how to get one object by id, it will be like:
def print_document(request, doc_id):
and something like that, and where url for function will be look like that:
url(r'^print_documents/(?P<doc_id>[a-z\d]{24})/$', invoices.print_documents, name='print_documents')
and new page link will be like that localhost:8000/documents/print_documents/{doc_id}
and this method I can just call like :
print
but now I want to select several documents and send doc_ids, and I know that I can to like method above but I don't want big link. And how I can send array of ids to back end correctly?
now I have something like that:
printAll.on("click", function(){
var invoicesID = [];
$('input.select-inv-check:checked').each(function() {
invoicesID.push($(this).data('docid'));
});
var url = Globals.printAll;
$.post( url, { doc_ids: invoicesID } ).done(function(result) {
console.log("result", result[0].Docs);
if(result.code == 0){
}else{
alert(result.message);
}
});
});
And I know that it doesn't correct! pls help