return Tuple to js in view - javascript

Tried using c# 7 Tuples like
public (string, bool) ProcessForm([FromBody]Dictionary<string,string> contactFormRequest)
But I get the error "CS1031: Type expected". I guess this isn't supported yet.
Then I tried
public Tuple<string, bool> ProcessForm([FromBody]Dictionary<string,string> contactFormRequest)
{
var message = "test";
var result = true;
var tuple = new Tuple<string, bool>(message, result);
return tuple;
}
This gives no error, but then I cannot pick it up in the view file
function handleResult(data) {
$("#custommessages").html(data.Item1);
}
$2sxc(#Dnn.Module.ModuleID).webApi.post("Form/ProcessForm", {}, newItem, true).then(handleResult);
This outputs nothing.
If I return a simple string from the controller, "data" picks it fine.
How do you pick up the values from a Tuple return?

Why not create a POCO class for serialization:
public class SomeResult
{
public string Message{get;set;}
public bool Result{get;set;}
}
then
public SomeResult ProcessForm([FromBody]Dictionary<string,string> contactFormRequest)
{
var message = "test";
var result = true;
return new SomeResult{Message = message, Result = result};
}

Why not just return a IActionResult?
You can simply write an Anonymous type instead of Tuple!
Named Types may take up some useless spaces (As I thinks that...)
Try This:
public IActionResult ProcessForm([FromBody]Dictionary<string,string> contactFormRequest)
{
var message = "test";
var result = true;
//This will create an anonymous type! (you can see its named as "a'")
var resultData = new { Message = message, Result = result };
return Json(resultData);
}
Wish it may help you.

Related

Alfresco datalist send email on very new item creation

I have applied rule on datalist folder like on each item creation, it should drop an email to respective person.
Below is the script for the same:
function main()
{
var site = siteService.getSite("hardik-test");
var dataListsContainer = site.getContainer("datalists");
var dataLists = dataListsContainer.getChildren();
var fullName, manager,joiningDate;
for(var x=0;x<dataLists.length;x++)
{
var dataList = dataLists[x];
var props = dataList.getProperties();
var title = props["cm:title"];
if(title.equals("Employee"))
{
var dataListItems = dataList.getChildren();
for (var y = 0; y < dataListItems.length; y++)
{
var dataListItem = dataListItems[dataListItems.length-1];
var dataListItemProps = dataListItem.getProperties();
fullName = dataListItemProps["emp:fullName"];
manager = dataListItemProps["emp:manager"];
joiningDate = dataListItemProps["emp:joiningDate"];
}
}
}
// create mail action
var mail = actions.create("mail");
mail.parameters.to = "xyz#xyz.com"; //manager email id should be there
mail.parameters.subject = "Task assigned to you.";
mail.parameters.from = "xyz#xyz.com";
//mail.parameters.template = companyhome.childByNamePath("Data Dictionary/Email Templates/Notify Email Templates/notify_user_email.html.ftl");
mail.parameters.text = "Hi "+manager +"," + "\n A new employee " +fullName +" will be joining our team on "+ joiningDate + "." +
"\n For details, Please click here. \n Regards, \n Administrator" ;
mail.execute(document);
}
script is running every time when we create new item but in the email it's not fetching the latest data we entered.
If we want to use email template, then how can we pass parameter(custom values) to email template?
Want to create link that will redirect to datalist.
This is one of the many times when the Alfresco source can be instructive. If you take a look at the MailActionExecuter class you'll see that it has several parameters defined:
public static final String NAME = "mail";
public static final String PARAM_LOCALE = "locale";
public static final String PARAM_TO = "to";
public static final String PARAM_CC = "cc";
public static final String PARAM_BCC = "bcc";
public static final String PARAM_TO_MANY = "to_many";
public static final String PARAM_SUBJECT = "subject";
public static final String PARAM_SUBJECT_PARAMS = "subjectParams";
public static final String PARAM_TEXT = "text";
public static final String PARAM_HTML = "html";
public static final String PARAM_FROM = "from";
public static final String PARAM_FROM_PERSONAL_NAME = "fromPersonalName";
public static final String PARAM_TEMPLATE = "template";
public static final String PARAM_TEMPLATE_MODEL = "template_model";
public static final String PARAM_IGNORE_SEND_FAILURE = "ignore_send_failure";
public static final String PARAM_SEND_AFTER_COMMIT = "send_after_commit";
One of those is PARAM_TEMPLATE_MODEL which you would set by using "template_model". The "model" in that parameter is what should be catching your eye. It means you can pass in a set of keys and values by using that parameter.
Later, in the source for that class we see where the parameter is read and then used to build the full model that is then passed in to the Freemarker template:
Map<String, Object> suppliedModel = null;
if(ruleAction.getParameterValue(PARAM_TEMPLATE_MODEL) != null)
{
Object m = ruleAction.getParameterValue(PARAM_TEMPLATE_MODEL);
if(m instanceof Map)
{
suppliedModel = (Map<String, Object>)m;
}
else
{
logger.warn("Skipping unsupported email template model parameters of type " + m.getClass().getName() + " : " + m.toString());
}
}
// build the email template model
Map<String, Object> model = createEmailTemplateModel(actionedUponNodeRef, suppliedModel, fromPerson, toRecipients);
So, if you comment in the reference to the template and you pass in an additional parameter to the action, assuming your template makes use of the items you add to the model, you should see those in the resulting email.
Your code would look something like:
var templateModel = {};
templateModel["fullName"] = fullName;
templateModel["manager"] = manager;
templateModel["joiningDate"] = joiningDate;
mail.parameters.template_model = templateModel;

Is it possible to return a string from C# to Javascript using Xamarin.iOS?

I have used HybridWebView from XLabs to build a HybridWebView that can communicate with C# code. I have build custom renderers to do this. In simple terms I have:
iOS
public class HybridWebViewRenderer : ViewRenderer<HybridWebView, WKWebView>, IWKScriptMessageHandler
{
const string JavaScriptFunctionTemplate = "function {0}(){{window.webkit.messageHandlers.invokeAction.postMessage('{0}|' + JSON.stringify(arguments));}}";
protected override void OnElementChanged(ElementChangedEventArgs<HybridWebView> e)
{
base.OnElementChanged(e);
if (Control == null)
{
userController = new WKUserContentController();
foreach (var f in Element.RegisteredFunctions.Where(ff => !ff.IsInjected))
{
var script = new WKUserScript(new NSString(string.Format(JavaScriptFunctionTemplate, f.Name)), WKUserScriptInjectionTime.AtDocumentEnd, false);
userController.AddUserScript(script);
f.Injected();
}
userController.AddScriptMessageHandler(this, "invokeAction");
var config = new WKWebViewConfiguration { UserContentController = userController };
var webView = new WKWebView(Frame, config)
{
NavigationDelegate = new CustomWKNavigationDelegate(this.Element)
};
SetNativeControl(webView);
}
if (e.OldElement != null)
{
userController.RemoveAllUserScripts();
userController.RemoveScriptMessageHandler("invokeAction");
var hybridWebView = e.OldElement as HybridWebView;
hybridWebView.Cleanup();
}
if (e.NewElement != null)
{
Load(Element.Uri);
}
}
public void DidReceiveScriptMessage(WKUserContentController userContentController, WKScriptMessage message)
{
var bits = message.Body.ToString().Split('|');
if (bits.Count() == 2)
{
var result = Element.InvokeFunction(bits[0], bits[1]);
//How do I return result back to Javascript function?
}
}
the InvokeFunction method returns a value result which is a string.
How can I return this string result back to the javascript function which was injected?
Edit
Do I need to edit my JavaScriptFunctionTemplate I notice in the XLabs they have a similar template but append something to the end
Is there any reason why you couldn't simply 're-call' your function using the methods described here?
Their example:
void OnCallJavaScriptButtonClicked (object sender, EventArgs e)
{
...
int number = int.Parse (numberEntry.Text);
int end = int.Parse (stopEntry.Text);
webView.Eval (string.Format ("printMultiplicationTable({0}, {1})", number, end));
}
So yours would be something like:
const string JavaScriptFunctionTemplate = "function {0}(){{window.webkit.messageHandlers.invokeAction.postMessage('{0}|' + JSON.stringify(arguments));}}";
public void DidReceiveScriptMessage(WKUserContentController userContentController, WKScriptMessage message)
{
var bits = message.Body.ToString().Split('|');
if (bits.Count() == 2)
{
var result = Element.InvokeFunction(bits[0], bits[1]);
webView.Eval(string.Format ("JavaScriptFunctionTemplate({0})", result)); // or however your parameter structure is.
}
}
EDIT:
Just want to encorporate the LINK that the OP found as it looks to be a solid guide to the solution in Objective-C which is fairly straight forward to convert to Xamarin C#.

JavaScript equivalent of .NET XML Deserialization

I'm looking for a JavaScript library that can deserialize/unmarshal XML (strings or DOM) to JavaScript classes in a way similar to the .NET XmlSerializer's Deserialize method.
The functionality I'm looking for:
Classes are defined as JavaScript constructor functions.
Mapping between nodes and classes/properties is configurable.
Deserialization result consists of instances of these classes.
For example, the following XML:
<root textAttribute='text1' numberAttribute='1' attributeToIgnore1='ignored1' attributeToIgnore2='ignored2'>
<children>
<child>text2</child>
<child>text3</child>
</children>
<childToIgnore>ignored3</childToIgnore>
</root>
used with JavaScript definitions similar to these:
function RootClass() {
this.stringProperty = "";
this.integerProperty = 0;
this.collectionProperty = [];
}
function ChildClass() {
this.stringProperty = "";
}
should produce JavaScript objects similar to the following:
var result = new RootClass();
result.textProperty = "text1";
result.integerProperty = 1;
result.collectionProperty = [];
result.collectionProperty[0] = new ChildClass();
result.collectionProperty[0].textProperty = "text2";
result.collectionProperty[1] = new ChildClass();
result.collectionProperty[1].textProperty = "text3;
An example of .NET (C#) code that does the same would be something like (see this .NET Fiddle for a working example):
public class Program
{
public static void Main()
{
var result = Serializer.Deserialize();
Console.WriteLine("text: {0}", result.StringProperty);
Console.WriteLine("number: {0}", result.IntegerProperty);
Console.WriteLine("enum: {0}", result.EnumProperty);
Console.WriteLine("child[0].Value: {0}", result.CollectionProperty[0].Value);
Console.WriteLine("other#[0]: {0}", result.OtherAttributes[0].InnerText);
Console.WriteLine("other*[0]: {0}", result.OtherElements[0].InnerText);
}
}
public static class Serializer
{
public static RootClass Deserialize()
{
var type = typeof (RootClass);
var serializer = new XmlSerializer(type);
var xmlString = #"
<root textAttribute='text1' numberAttribute='1' enumAttribute='item1' attributeToIgnore1='ignored1' attributeToIgnore2='ignored2'>
<children>
<child>text2</child>
<child>text3</child>
</children>
<childToIgnore>ignored3</childToIgnore>
</root>";
using (var stringReader = new StringReader(xmlString))
{
return serializer.Deserialize(stringReader) as RootClass;
}
}
}
[XmlRoot("root")]
public class RootClass
{
[XmlAttribute("textAttribute")]
public string StringProperty;
[XmlAttribute("numberAttribute")]
public int IntegerProperty;
[XmlAttribute("enumAttribute")]
public Enumeration EnumProperty;
[XmlAnyAttribute]
public XmlAttribute[] OtherAttributes;
[XmlArray("children")]
[XmlArrayItem("child")]
public Collection<ChildClass> CollectionProperty;
[XmlAnyElement]
public XmlElement[] OtherElements;
}
public enum Enumeration
{
[XmlEnum("item1")]
Item1,
[XmlEnum("item2")]
Item2
}
public class ChildClass
{
[XmlText]
public string Value;
}
Jsonix by Alexey Valikov (source, guide) can deserialize XML to JavaScript based on configurable mapping.
I've contributed code to support deserializing custom classes using instance factories. This will hopefully make it into the next release of Jsonix (2.0.11).
var input = "<element1 attribute1='value1' />";
var Class1 = function () {};
Class1.prototype.toString = function () {
return this.Property1;
};
var mapping = {
elementInfos: [{
elementName: "element1",
typeInfo: new Jsonix.Model.ClassInfo({
name: "Element1",
instanceFactory: Class1,
propertyInfos: [
new Jsonix.Model.AttributePropertyInfo({
name: "Property1",
attributeName: "attribute1"
})
]
})
}]
};
var context = new Jsonix.Context([mapping]);
var unmarshaller = context.createUnmarshaller();
var result = unmarshaller.unmarshalString(input).value;
console.log(result.toString()); // logs "value1"
A longer working example on JSFiddle uses XML from question.

How can I return an empty string (or null) for a PartialViewResult?

I have a method which registers a vote for a comment. If there are no errors while casting the vote, I return a small snippet of html via a PartialViewResult to update the page.
If it does not succeed, nothing should happen. I need to test for this condition on the client side.
The server-side method:
[HttpPost]
public PartialViewResult RegisterVote(int commentID, VoteType voteType) {
if (User.Identity.IsAuthenticated) {
var userVote = repository.RegisterVote((Guid)Membership.GetUser().ProviderUserKey, commentID, voteType);
if (userVote != null) {
return PartialView("VoteButtons", userCommentVote.Comment);
}
}
return null;
}
The client side script:
$(document).on("click", ".vote img", function () {
var image = $(this);
var commentID = GetCommentID(image);
var voteType = image.data("type");
$.post("/TheSite/RegisterVote", { commentID: commentID, voteType: voteType }, function (html) {
image.parent().replaceWith(html);
});
});
If the vote was recorded, the "html" variable containes markup as expected. If it does not succeed (i.e. null was returned) then the "html" variable is instead a "Document" object with a parse error.
Is there a way to return an empty string from the PartialViewResult and then just test for length? Is there a different/better way to do this?
Change your method signature from: public PartialViewResult
To: public ActionResult
Then instead of returning null, return this:
return Json("");
This will allow you to return a partial view if successful, if not, it will just return JSON with an empty string as the value. Your current JS will work as is. From MSDN:
The ActionResult class is the base class for action results.
The following types derive from ActionResult:
ContentResult
EmptyResult
FileResult
HttpUnauthorizedResult
JavaScriptResult
JsonResult
RedirectResult
RedirectToRouteResult
ViewResultBase
This is what allows you to return different derived types in your method.
It would be better to return a JsonResult as,
[HttpPost]
public JsonResult RegisterVote(int commentID, VoteType voteType)
{
JsonResult result = new JsonResult();
object content;
if (User.Identity.IsAuthenticated)
{
var userVote = repository.RegisterVote((Guid)Membership.GetUser().ProviderUserKey, commentID, voteType);
if (userVote != null)
{
content = new
{
IsSuccess = true,
VoteButtons = userCommentVote.Comment
};
}
else
{
content = new { IsSuccess = false };
}
}
result.Data = content;
return result;
}
In Ajax call, you can validate if IsSuccess is true or false.

angular promise returning __proto__

I have an asp.net-mvc app using angular. I had a get method that returns some data from the server. What I was returning was a Tuple with a status message and a second piece of data that was either an error message or the actual data. Ex:
return Json(new Tuple<string, string>("error", "bad request"));
//or
return Json(new Tuple<string, MyData>("success", new MyData());
this was working fine, in angular I did the following:
$http.get(url).then(
function (result) {
return result.data;
},
function (result) {
$q.reject(result.data);
}
here, result.data.Item1 was the first item of my Tuple
However, I changed my return types from Tuple to a new custom type that I created that looks like the following:
public class ServerResponse <T1, T2, T3>
{
T1 status { get; set; }
T2 message { get; set; }
T3 data { get; set; }
public ServerResponse(T1 status, T2 message, T3 data)
{
this.status = status;
this.message = message;
this.data = data;
}
}
but now when I do:
result.data.status
I dont get expected results because result.data is returning something like this:
__proto__ : Object
and I'm not sure how to fix this.
after looking around and comparing to the Tuple class, I noticed that my ServerResponse class's properties were not marked public so they weren't being found. After making them public the problem went away

Categories

Resources