AEM - How to tweak activation error message - aem

We are working in an AEM 6.1 environment and have created an activation preprocessor that will stop pages from being activated if certain attributes are not set. That works great but we'd also like to change the error message that's displayed by the activation process when the preprocessor throws a ReplicationExcdeption. Can anyone point me to the code that actually displays the error message?

We overrided several functions in SiteAdmin.Actions.js. Copy it from libs folder /apps/cq/ui/widgets/source/widgets/wcm/SiteAdmin.Actions.js or use CQ.Ext.override
We need to override CQ.wcm.SiteAdmin.scheduleForActivation and CQ.wcm.SiteAdmin.internalActivatePage methods.
We do it with using the following code
CQ.wcm.SiteAdmin.internalActivatePage = function(paths, callback) {
if (callback == undefined) {
// assume scope is admin and reload grid
var admin = this;
callback = function(options, success, response) {
if (success) admin.reloadPages();
else admin.unmask();
};
}
preActionCallback = function(options, success, response) {
if (success) {
var responseObj = CQ.Util.eval(response);
if (responseObj.activation) {
CQ.HTTP.post(
CQ.shared.HTTP.externalize("/bin/replicate.json"),
callback,
{ "_charset_":"utf-8", "path":paths, "cmd":"Activate" }
);
} else {
CQ.wcm.SiteAdmin.preactivateMessage(responseObj);
}
}else{
CQ.Ext.Msg.alert(
CQ.I18n.getMessage("Error"), CQ.I18n.getMessage("Could not activate page."));
}
admin.unmask();
};
CQ.HTTP.get(
"/apps/sling/servlet/content/preActivateValidator.html?path=" + paths,
preActionCallback
);
};
This path /apps/sling/servlet/content/preActivateValidator.html (You can use any other link and extension) returns json with some info about messages, which are parsed in custom method and generates custom error messages CQ.wcm.SiteAdmin.preactivateMessage:
CQ.wcm.SiteAdmin.preactivateMessage = function(responseObj) {
var message = "";
var incorrectItems = responseObj.incorrectItems;
if (responseObj.countOfIncorrectItems > 1) message = message + "s";
if (responseObj.missingMetadata) {
message = message + "Please, set \"Programming Type\" for next videos:<br/>";
var missingMetadataPaths = responseObj.missingMetadata;
for(var i = 0; i < missingMetadataPaths.length; i++){
message = message + ""+missingMetadataPaths[i].path+"<br/>";
}
message += "<br/>";
}
if(message == ""){
message = "Unknown error.";
}
CQ.Ext.Msg.alert(
CQ.I18n.getMessage("Error"), CQ.I18n.getMessage(message));
}
So you can implement component or servlet which will verify your attributes and will generate JSON.

Related

How to find if one of the element is present after the page is displayed

The protractor has to verify whether the error message is present in the page. So the error message can be either in "alert-message" class or in "fail-heading" class.
If i do like below it is successful only if the alert-message className is displayed. But sometimes i get the className as "fail-heading".
var waitforele_confirmation = by.className('alert-message');
browser.wait(function(){return browser.driver.isElementPresent(waitforele_confirmation)}, 60000);
expect(browser.driver.isElementPresent(waitforele_confirmation)).toBeTruthy();
So i want to dynamically check which element is present after the page is loaded. Also i want to use the browser.wait function when waiting for each element. I just did the below pseudo code just to understand.
while (i<120 and !found)
{
int i=0;
if (element(by.className('alert-message')).isPresent())
{
found = true;
}
else if (element(by.className('fail-heading')).isPresent())
{
found = true;
}
else
{
browser.sleep(500);
}
i++;
}
Can someone convert the pseudo code in protractor pls?
let EC = protractor.ExpectedConditions;
let alertMessageVisibility = EC.visibilityOf($('.alert-message'));
let failHeadingVisibility = EC.visibilityOf($('.fail-heading'));
browser.wait(EC.or(alertMessageVisibility, failHeadingVisibility), 60000, "Alert message or fail heading should become visible in 60 seconds, but it wasn't")
Below code will work as you expected:
var EC = protractor.ExpectedConditions;
var alertMessageElement = element(by.className('alert-message'))
var failHeadingElement = element(by.className('fail-heading'))
/*browser.wait() will be keep on checking for error messages until either
any one of the error message found or specified timeout limit reached*/
browser.wait(function(){
EC.visibilityOf(alertMessageElement).call().then(function(isAlertMessagePres
ent){
if(isAlertMessagePresnt){
return true;
}
})
EC.visibilityOf(failHeadingElement).call().then(function(isFailedHeadingPresent) {
if(isFailedHeadingPresent){
return true;
}
})
},10000,'No error message found within specified timeout of 10 seconds
');

Xamarin.Forms Consume Rest Service

I'm new to Xamarin and developing native apps in general (I have made html5 apps in the past).
I have started on a Xamarin.Forms project and I'm trying to contact a REST like API (need to GET an URL which will return a json array).
Normally from C# I would use RestSharp and perform this call using the RestClient.
I'm not having any luck installing that package from Xamarin Studio though, but I have got the Microsoft HTTP Libraries installed.
I'm pretty sure this is a very trivial task to perform, I just haven't been able to adapt the samples I have found online to work for me.
Anyone who could post how this is done please (remember I'm new to this so don't expect me to understand everything that is different from say a normal console app)?
It is easy with HTTP Client and JSON.NET here is a example of a GET:
public async Task<List<Appointment>> GetDayAppointments(DateTime day)
{
HttpClient client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", "Bearer " + App.apiToken);
//Your url.
string resourceUri = ApiBaseAddress;
HttpResponseMessage result = await client.GetAsync (resourceUri, CancellationToken.None);
if (result.IsSuccessStatusCode) {
try {
return GetDayAppointmentsList(result);
} catch (Exception ex) {
Console.WriteLine (ex.Message);
}
} else {
if(TokenExpired(result)){
App.SessionExpired = true;
App.ShowLogin();
}
return null;
}
return null;
}
private List<Appointment> GetDayAppointmentsList(HttpResponseMessage result){
string content = result.Content.ReadAsStringAsync ().Result;
JObject jresponse = JObject.Parse (content);
var jarray = jresponse ["citas"];
List<Appointment> AppoinmentsList = new List<Appointment> ();
foreach (var jObj in jarray) {
Appointment newApt = new Appointment ();
newApt.Guid = (int)jObj ["id"];
newApt.PatientId = (string)jObj ["paciente"];
newApt.Name = (string)jObj ["nombre"];
newApt.FatherLstName = (string)jObj ["paterno"];
newApt.MotherLstName = (string)jObj ["materno"];
string strStart = (string)jObj ["horaIni"];
TimeSpan start;
TimeSpan.TryParse (strStart, out start);
newApt.StartDate = start;
string strEnd = (string)jObj ["horaFin"];
TimeSpan end;
TimeSpan.TryParse (strEnd, out end);
newApt.EndDate = end;
AppoinmentsList.Add (newApt);
}
return AppoinmentsList;
}
I use System.Net.WebClient and our asp.net WebAPI interface:
public string GetData(Uri uri)
{//uri like "https://webapi.main.cz/api/root"
string ret = "ERROR";
try
{
using (WebClient webClient = new WebClient())
{
//You can set webClient.Headers there
webClient.Encoding = System.Text.Encoding.UTF8;
ret = webClient.DownloadString(uri));//Test some data received
//In ret you can have JSON string
}
}
catch (Exception ex) { ret = ex.Message; }
return ret;
}
4
public string SendData(Uri uri, byte[] data)
{//uri like https://webapi.main.cz/api/PostCheckLicence/
string ret = "ERROR";
try
{
using (WebClient webClient = new WebClient())
{
webClient.Headers[HttpRequestHeader.Accept] = "application/octet-stream";
webClient.Headers[HttpRequestHeader.ContentType] = "text/bytes";
webClient.Encoding = System.Text.Encoding.ASCII;
byte[] result = webClient.UploadData(uri, data);
ret = Encoding.ASCII.GetString(result);
if (ret.Contains("\"ResultWebApi\":\"OK"))
{//In ret you can have JSON string
}
else
{
}
}
}
catch (Exception ex) { ret = ex.Message; }
return ret;
}
x
I've some examples in my Github repo. Just grab the classes there and give them a try. The API is really easy to use:
await new Request<T>()
.SetHttpMethod(HttpMethod.[Post|Put|Get|Delete].Method) //Obligatory
.SetEndpoint("http://www.yourserver.com/profilepic/") //Obligatory
.SetJsonPayload(someJsonObject) //Optional if you're using Get or Delete, Obligatory if you're using Put or Post
.OnSuccess((serverResponse) => {
//Optional action triggered when you have a succesful 200 response from the server
//serverResponse is of type T
})
.OnNoInternetConnection(() =>
{
// Optional action triggered when you try to make a request without internet connetion
})
.OnRequestStarted(() =>
{
// Optional action triggered always as soon as we start making the request i.e. very useful when
// We want to start an UI related action such as showing a ProgressBar or a Spinner.
})
.OnRequestCompleted(() =>
{
// Optional action triggered always when a request finishes, no matter if it finished successufully or
// It failed. It's useful for when you need to finish some UI related action such as hiding a ProgressBar or
// a Spinner.
})
.OnError((exception) =>
{
// Optional action triggered always when something went wrong it can be caused by a server-side error, for
// example a internal server error or for something in the callbacks, for example a NullPointerException.
})
.OnHttpError((httpErrorStatus) =>
{
// Optional action triggered when something when sending a request, for example, the server returned a internal
// server error, a bad request error, an unauthorize error, etc. The httpErrorStatus variable is the error code.
})
.OnBadRequest(() =>
{
// Optional action triggered when the server returned a bad request error.
})
.OnUnauthorize(() =>
{
// Optional action triggered when the server returned an unauthorize error.
})
.OnInternalServerError(() =>
{
// Optional action triggered when the server returned an internal server error.
})
//AND THERE'S A LOT MORE OF CALLBACKS THAT YOU CAN HOOK OF, CHECK THE REQUEST CLASS TO MORE INFO.
.Start();
And there's a couple of examples.
For all my Xamarin Forms app I use Tiny.RestClient.
It's easy to get it and easy to use it.
You have to download this nuget.
And after it just very easy to use it :
var client = new TinyRestClient(new HttpClient(), "http://MyAPI.com/api");
var cities = client.
GetRequest("City").
AddQueryParameter("id", 2).
AddQueryParameter("country", "France").
ExecuteAsync<City>> ();
Hopes that helps.

How to write to log from vscode extension?

I am attempting to develop an extension with a language-server for VSCode. I am trying to figure out how to write text to log from language-server part of the extension. console.log produces nothing
Just as an update, you can use vscode.window.createOutputChannel to create the output container and then write to it with the appendLine method.
//Create output channel
let orange = vscode.window.createOutputChannel("Orange");
//Write to output.
orange.appendLine("I am a banana.");
Just open vscode and go to menu "Help"->"Toggle Developer Tools" and the console is displayed on rigth window.
On server side try using connection.console.log.
// Create a connection for the server. The connection uses
// stdin / stdout for message passing
let connection: IConnection = createConnection(process.stdin, process.stdout);
connection.console.log(`Console test.`);
The message with show in Debug console on client side.
For client side simple console.log works well for me.
You have to set an outputChannelName property on the client options inside the client extension code:
let clientOptions: LanguageClientOptions = {
outputChannelName: 'XYZ Language Server',
};
Once you've done that you can use console.log() and it will be shown in the VSCode extension output panel.
The Language Server Protocol supports logging, use the notification window/logMessage to send log messages from the server, VS Code will display the server's log in the output panel, in the channel corresponding to the language client that started the server.
Thanks guys!
export let config: any = {};
export function getConfig() {
//debug
config.debug = workspace.getConfiguration().get('VBI.debug');
config.debugToChannel = workspace.getConfiguration().get('VBI.debugToChannel'); //Instead into dev-tools-console
return config;
}
/**
* #param cat Type String --> define Cathegory [info,warn,error]
* #param o Rest Parameter, Type Any --> Data to Log
*/
export let info = vscode.window.createOutputChannel("VBI-Info");
export function log(cat: string, ...o: any) {
function mapObject(obj: any) {
switch (typeof obj) {
case 'undefined':
return 'undefined';
case 'string':
return obj;
case 'number':
return obj.toString;
case 'object':
let ret: string = '';
for (const [key, value] of Object.entries(obj)) {
ret += (`${key}: ${value}\n`);
}
return ret;
default:
return obj; //function,symbol,boolean
}
}
if (config.debug) {
if (config.debugToChannel) {
switch (cat.toLowerCase()) {
case 'info':
info.appendLine('INFO:');
o.map((args: any) => {
info.appendLine('' + mapObject(args));
});
info.show();
return;
case 'warn':
info.appendLine('WARN:');
o.map((args: any) => {
info.appendLine('' + mapObject(args));
});
info.show();
return;
case 'error':
let err:string='';
info.appendLine('ERROR: ');
//err += mapObject(cat) + ": \r\n";
o.map((args: any) => {
err += mapObject(args);
});
info.appendLine(err);
vscode.window.showErrorMessage(err);//.replace(/(\r\n|\n|\r)/gm,"")
info.show();
return;
default:
info.appendLine('INFO-Other:');
info.appendLine(mapObject(cat));
o.map((args: any) => {
info.appendLine('' + mapObject(args));
});
info.show();
return;
}
}
else {
switch (cat.toLowerCase()) {
case 'info':
console.log('INFO:', o);
return;
case 'warn':
console.log('WARNING:', o);
return;
case 'error':
console.log('ERROR:', o);
return;
default:
console.log('log:',cat, o);
return;
}
}
}
}
tests:
import * as func from './functions';
import { config } from './functions';
func.getConfig();
let text = `debugToChannel:${config.debugToChannel}\n`;
func.log('info','vbi-format',text);
func.log('warn','vbi-format',text);
func.log('error','vbi-format',text);

DotNetNuke Service API Authorization throwing 401 Unauthorized code

I am having a bit of difficulty figuring out why I am getting 401 Unauthorized status from service framework. At the moment I have it setup to allow everyone to do as they please but that because when I try to enable authorisation I get 401 error code.
//[SupportedModules("Boards")]
//[DnnModuleAuthorize(AccessLevel = SecurityAccessLevel.View)]
[AllowAnonymous]
public class BoardsServiceController : DnnApiController
{ ... }
The strange thing is I have another module which is more than happy to work away with DnnModuleAuthorize
[SupportedModules("Assignments")]
[DnnModuleAuthorize(AccessLevel = SecurityAccessLevel.View)]
public class AsgnsServiceController : DnnApiController
{ ... }
In both cases I have checked to make sure the user has permissions to view the page on which the module lives.
I have cross referenced both projects and everything seems to be spot on. Yet one is working away just fine and the other one returns 401.
Any suggestions?
Update
For Assignments module I am mostly using jQuery style of ajax request just because I haven't got around to revising the module. So a typical GET request would look something like this:
$.ajax({
type: "GET",
url: sf.getServiceRoot( "Assignments" ) + "AsgnsService/GetAssignments",
data: data,
beforeSend: sf.setModuleHeaders
}).done( function ( items ) {
//removed for brevity
}).fail( function ( xhr, result, status ) {
//removed for brevity
});
As for Boards module the code structure is slightly different due knockout implementation. There is a dedicated ServiceCaller but it all boils down to the same ajax call to the server except that instead of having full blown ajax call defined as above it looks much neater.
var that = this;
that.serviceCaller = new dnn.boards.ServiceCaller($, this.moduleId, 'BoardsService');
var success = function (model) {
if (typeof model !== "undefined" && model != null) {
viewModel = new boardViewModel(model.colLists);
ko.bindingHandlers.sortable.beforeMove = viewModel.verifyAssignments;
ko.bindingHandlers.sortable.afterMove = viewModel.updateLastAction;
// normally, we apply moduleScope as a second parameter
ko.applyBindings(viewModel, settings.moduleScope);
}
//console.log('success', model);
};
var failure = function (response, status) {
console.log('request failure: ' + status);
};
var params = {
BoardId: this.boardId
};
that.serviceCaller.get('GetBoardLists', params, success, failure);
And the ServiceCaller ajax function itself looks like this:
function (httpMethod, method, params, success, failure, synchronous) {
var options = {
url: that.getRoot() + method,
beforeSend: that.services.setModuleHeaders,
type: httpMethod,
async: synchronous == false,
success: function (d) {
if (typeof (success) != 'undefined') {
success(d || {});
}
},
error: function (xhr, textStatus, errorThrown) {
if (typeof (failure) != 'undefined') {
var message = undefined;
if (xhr.getResponseHeader('Content-Type').indexOf('application/json') == 0) {
try {
message = $.parseJSON(xhr.responseText).Message;
} catch (e) {
}
}
failure(xhr, message || errorThrown);
}
}
};
if (httpMethod == 'GET') {
options.data = params;
} else {
options.contentType = 'application/json; charset=utf-8';
options.data = ko.toJSON(params);
options.dataType = 'json';
}
$.ajax(options);
};
This would be the two GET requests from two different modules where one is happy and the other throws a status 401 when I enable the same annotations.
Does this provide any clues?
Update
Now in saying all of the above if one takes a look at the original Boards module code base one will notice [DnnAuthorize] annotation attached to every function.
During module revision I removed all instances of [DnnAuthorize] annotation and replaced it with two of my own on the service class itself.
When I add [DnnAuthorize] as annotation on service class itself things work as expected. So why [SupportedModules("Boards")] and [DnnModuleAuthorize(AccessLevel = SecurityAccessLevel.View)] combination doesn't !?
I am not sure but working with the WebAPI you have to register the Service Framework anti forgery stuff
ServicesFramework.Instance.RequestAjaxAntiForgerySupport();
This is part of asking the API to work with a specific module.

How to get alerts from action in asp.net mvc

as far as I know we can not call the javascript method in controller's action method. but how to consider that a particular code line get executed ? As i asked earlier here
we must have to get acknowledgment that line number so and so get executed. see this action in my controller
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult uploadfile(FormCollection fc)
{
UserMaster objUMaster = objAM.GetUser(new Guid(fc["userIdForFile"].ToString()));
try
{
string imagename = "";
//Check for files uploaded here.
foreach (string inputTagName in Request.Files)
{
HttpPostedFileBase file = Request.Files[inputTagName];
imagename = objUMaster.UserId.ToString() + file.FileName;
if (file.ContentLength > 0)
{
string filePath = Path.Combine(HttpContext.Server.MapPath("../Content/UserUploads"), objUMaster.UserId.ToString() + Path.GetFileName(file.FileName));
file.SaveAs(filePath);
string filePathThumb = Path.Combine(HttpContext.Server.MapPath("../Content/UserUploads/Thumbnails"), objUMaster.UserId.ToString() + Path.GetFileName(file.FileName));
var fl = Request.Files.Get(inputTagName);
Stream strm = fl.InputStream;
Image img = Image.FromStream(strm);
ResizeAndSaveHighQualityImage(img, 120, 120, filePathThumb, 100);
}
}
objUMaster.ProfilePhoto = imagename;
objAM.Save();
return RedirectToAction("EditProfile", new { id = objUMaster.UserId });
}
catch (Exception ex)
{
//SendEmail(ex.Message);
string strPath = HttpContext.Server.MapPath("../Content/UserUploads");
StreamWriter SW;
SW = System.IO.File.CreateText(strPath+"/log.txt");
SW.WriteLine(ex.Message.ToString());
SW.Close();
return RedirectToAction("EditProfile", new { id = objUMaster.UserId });
}
}
Here I am trying to upload the image in my domains file system (dir). but I want get alert so that I can confirm , this lie get executed successfully. because nothing happening as expected from this action. so can we call Javascript's "alert", or something else remedy?
Some pointers to help you:
See if Network service/account under which your application is running has permission on the location where you are saving your file.
Besides this to make sure that your file is saved, after save call you can make another call File.IsExist. If it exists then you can log the success/failure in some log file. Wouldn't that work for you?