I'm currently working on a project that uses ASP.NET Boilerplate framework and I'm starting to get the hang of using DTOs.
So I'm trying to implement an upload function where I can upload files/images, but using DTO instead of directly calling it from the controller. I would like some guidance on how to create it from DTO, including AppServices and the JavaScript, if anyone could help me.
You have to use IFormFile as a parameter of your service method.
Please find the sample code to use it. You can also create a Dto and declare an IFormFile property in Dto class and pass as a parameter to the method.
using Microsoft.AspNetCore.Http;
public async void UploadFile(IFormFile csvInput)
{
using (var stream = csvInput.OpenReadStream())
{
var currentLine = 0;
using (var reader = new StreamReader(stream))
{
...
}
}
}
Related
I would like to use Incremental DOM library in my GWT app.
https://google.github.io/incremental-dom/#about
As I am coming from the Java world, I struggle with concepts of JavaScript namespaces and modules. I was able to use Closure Compiler with closure version of Incremental DOM (has to be build from sources).
It starts with the following line:
goog.module('incrementaldom');
So if I was to use it in regular JS I would type:
var patch = goog.require('incrementaldom').patch;
And then the patch function would be available in the scope of my code. But how to make it accessible from #JsInterop annotated classes?
I tried something like:
public class IncrementalDom {
#JsMethod(namespace = "incrementaldom", name = "patch")
public static native void patch(Element element, Patcher patcher);
#JsFunction
#FunctionalInterface
public interface Patcher {
void apply();
}
}
But it doesn't work. I get this error in the runtime:
(TypeError) : Cannot read property 'patch' of undefined
So I guess I have to somehow expose the incrementaldom module or at least only the patch method. But I don't know how.
After fighting for the whole day I found the solution. In the goog.module: an ES6 module like alternative to goog.provide document I found the missing information about the role of goog.scope function - required modules are visible only within the scoped call.
I created another Closure JS file named incrementaldom.js:
goog.provide('app.incrementaldom'); // assures creation of namespace
goog.require("incrementaldom");
goog.scope(function() {
var module = goog.module.get("incrementaldom");
var ns = app.incrementaldom;
app.incrementaldom.patch = module.patch;
});
goog.exportSymbol("app.incrementaldom", app.incrementaldom);
And now I can call it from Java code like this:
public class IncrementalDom {
#JsMethod(namespace = "app.incrementaldom", name = "patch")
public static native void patch(Element element, Patcher patcher);
#JsFunction
#FunctionalInterface
public interface Patcher {
void apply();
}
}
Still I have to define every object exported in original module separately in the Closure JS file. Fortunately I only need patch method. I hope one day I will find less cumbersome way for #JsInterop with goog.module :(
I'm trying to populate the array in my script (it's going to be used for charting with D3.JS later on). According to this post, I'm supposed to use the syntax below. However, it doesn't work, bacause I get the error on the pushy line saying Uncaught ReferenceError: WebSite is not defined, where WebSite is the name of the namespace of the data (I'm guessing that, as it's the name of my project).
<script>
var data = new Array();
#foreach (var piece in #Model.DataPieces)
{
#:data.push(#piece);
}
</script>
I'm pretty sure it has to do with the data type of piece, because the following change makes it work (at least not producing a bunch of errors). I'm picking out the individual fields from piece object and push those into the array, as a new object.
<script>
var data = new Array();
#foreach (var piece in #Model.DataPieces)
{
#:data.push({'cat': '#piece.Category', 'key': '#piece.Key', 'val': '#piece.Value'});
}
</script>
It's inconvenient, prone to mistakes and requires a refactoring of the assignment each time the model changes. How can I avoid this approach and be able to automagically create JSON objects upon assignment, as shown in the first sample?
The viewmodel for the Razor page is declared as folows.
namespace WebSite.Models
{
public class DrillDataViewModel
{
public List<DataPiece> DataPieces { get; set; }
public class DataPiece
{
public string Category { get; set; }
public string Key { get; set; }
public int Value { get; set; }
}
}
}
The line #:data.push(#piece); will be written to the output HTML as
data.push(<the result of calling ToString() on #piece>);
You need to replace #piece with something that will be evaluated to the JSON you want. This should work:
#:data.push(#Html.Raw(Json.Encode(piece)));
Or you can just output the whole array at once:
var data = #Html.Raw(Json.Encode(Model.DataPieces));
Try to pass this from Razor page to JavaScript.
#Html.Raw(#JsonConvert.SerializeObject(Model.DataPieces)
.Replace("{\"", "{")
.Replace(",\"", ",")
.Replace("\":", ":"))
The replaces serve to get rid of the invalid characters produced by default in the converter without you needing to play with streams or applying other libraries. Ugly but working.
Sometimes, I also add one more replace: .Replace("\"","'") to get a more JS like look. The outer method is needed so you don't get problems with & in the "e;.
This is a hand-on solution so if anybody knows a better way, I'd love to get some feedback.
Try
var yourJavascriptArray=#Html.Raw(Json.Encode(YouModel));
I have this javascript (I'm new to javascript so forgive me)
var data = [
['fff', 10.38],
['ddd', 56.33],
['ss', 24.03],
['ff', 4.77],
['dd', 0.91]
];
alert(data);
To me this looks like an array of arrays. and the alert gives:
fff,10.38,ddd,56.33,ss,24.03,ff,4.77,dd,0.91
I'm trying to create this in a c# Model - I've tried a lot but it never seems to provide exactly the same result.
alert('#Model.obs');
where the Model is:
//property
public object[] obs { get; set; }
//contructor
public EmployeeAbsenceChartViewModel()
{
object[] obbs1 = new object[2];
obbs1[0] = "rick";
obbs1[1] = 3;
object[] obbs2 = new object[2];
obbs2[0] = "rick";
obbs2[1] = 3;
obs = new object[] { obbs1, obbs2 };
}
the alert for the #Model.obs results in
System.Object[]
This should be pretty simple but the javascript that uses the data object doesn't like what I return from the model. I think I'm, missing something somewhere...
so, how would I recreate the var data object in my c# model?
When you directly write object to your View, it executes ToString() method.
In order to insert data in such format that JavaScript can work with it, you need to use JSON.
alert('#Html.Raw(JsonConvert.SerializeObject(Model.obs))');
Note that JsonConvert is a part of JSON.NET library which you can obtain using NuGet. Probably, you can use Json.Encode native method - it should work in the same way.
Within a <script> tag in a jsp file I have some code that looks like this:
var chart = new myChart({'id': ${user.id}, 'type': ${user.type}, 'name': {user.name});
Where user is a Spring model attribute set on the server side. My problem is that passing each different field of user feels clunky. It would be nice if I could do something like this:
var chart = new myChart('user': "${user}");
However when done this way the value of ${user} will be an object string that looks like this:
User{id=1, type='admin', name='foo'}
I know that I could just parse this string into an object in my external js, but it feels like there should be a cleaner way to do this. Thanks for the help.
EDIT: Going off of Cameron's answer below I could add this to my server-side controller code:
model.put("user", user);
String userJSON = MyJSONSerializer.serialize(user);
model.put("userJSON", userJSON);
Then in my JSP I could do:
var chart = new myChart({'user': JSON.parse('${userJSON}')});
This does solve my problem of having a messy options object, but it brings up the issue of using two model attributes for the same exact data. It would be ideal if I could use one model attribute for the user object, and then could somehow encode it to JSON on the fly.
You can convert the Object to JSON using a library like Jackson:
public static String objectAsJSON(Object obj) {
try
{
// This could be optimized by making a static ObjectMapper
return new ObjectMapper().writeValueAsString(obj);
}
catch (IOException e)
{
// Log exception and re-throw or return null
return null;
}
}
You could either call this method before putting the objectin your model and reference the String in your JSP like this:
var chart = ${jsonChart};
Or you could write a custom taglib and call objectAsJSON() from there. Then the actual myChart object could go in your model once. Your JSP might look like:
var chart = <chartlib:toJson obj="${chart}" />;
im thinking about replacing all my xml files and builders that i use for configuration with javascript / nashorn. lets say i have a java class that is builder style configuration object
class Configuration {
String name;
Configuration withName(String name) {
this.name = name;
return this;
}
int number;
Configuration withNumber(int number) {
this.number = number;
return this;
}
}
i would like to instantiate this class directly in javascript and have nashorn return to me an instance of it. i would like to code it in javascript like
{
name: 'qwerty',
number: 42
};
and then finally read the file, pass it into the script engine, and have it evaluate the object as an instance of Configuration.
is this possible with a json like syntax?
i wouldnt have a problem using the Packages.Configuration / Java.type("Configuration"); Java.extend(), but have yet to have any success with that.
or would i have to make / use a proper reader for the returned value?
No, Nashorn won't support this from what I've seen from available docs and JSR-223. You might need to use i.e. Jackson's ObjectMapper to deserialize JSON. And this should not be a problem, because Nashorn allows you to do almost anything in JavaScript: A JavaFX Script Application Examples.
You might also want to consider Groovy which has it's own map syntax which can be used inside constructors: Groovy Goodness: Using Lists and Maps As Constructors. Groovy is often used to define configuration.
You could cheat a little by attaching a converter function to your configuration type. This could be added easily on the JS side rather than trying to make it in Java.
var ConfigClass = Java.type('Configuration');
ConfigClass.fromJsObj = function(jsObj) {
var newConfig = new ConfigClass();
foreach(var prop in jsObj) {
newConfig[prop] = jsObj[prop];
}
return newConfig;
}
var myConfig = ConfigClass.fromJsObj( { name: "qwerty", number: 42 } );