ASP.NET, EntityFramework - Send minimal data to client - javascript

I have a javascript application with ASP.NET MVC 3, SignalR and Entity Framework in the backend. I have always to prepare the data, because i dont want to send all attributes to the client (performance issue? e.g person has address has country has ... and this for > 1000 person entities). So, now i create always a prepare function before i send the data to the client:
public void GetPeople()
{
PersonRepository personRepository = new PersonRepository(_context);
var pList = personRepository.GetAll();
var pClientList = prepare(pList);
Clients[Context.ConnectionId].loadPeople(pClientList);
}
private object prepare(IEnumerable<Person> pList)
{
return from p in pList
select new
{
id = p.ID,
firstName = p.FirstName,
lastName = p.LastName,
displayName = p.DisplayName
};
}
and i dont think this is a good practice, because i have to create always for each entity an prepare function and on complex entities it gets weird.

You should use AutoMapper for this.
It also supports flattening for complex types, and it's very easy to implement and use.

Related

UnityWebRequest.Put doesn't send JSON string

I'm looking to make a PUT or POST request to an API I've deployed to Vercel built with NEXT JS. It does other things besides being an API but that's not important...
So, I have a Unity Project where I would like to log the time that my player completed the level they're on.
Originally I wanted to use Firebase but discovered that I can't as the Windows Unity builds don't support it so I ended up just making an API that send the Data to MongoDB and does some other stuff, again not important.
So getting to the guts of the problem:
I have this IEnumerator to send the request:
IEnumerator logPlayerTime()
{
string url = "http://some-vercel-cloud-function/api/new";
var requestBody = new PlayerRequestBody();
requestBody.firstName = "John";
requestBody.lastName = "Doe";
requestBody.email = "email#email.com";
requestBody.marketing = false;
requestBody.time = 200000; // this actually come from somewhere else but for now this is fine
string json = JsonUtility.ToJson(requestBody);
UnityWebRequest request = UnityWebRequest.Put(url, json);
request.SetRequestHeader("Content-Type", "application/json");
request.SetRequestHeader("Accept", "*/*");
request.SetRequestHeader("Accept-Encoding", "gzip, deflate, br");
request.SetRequestHeader("Connection", "keep-alive");
request.useHttpContinue = false;
yield return request.SendWebRequest();
if (request.result != UnityWebRequest.Result.Success)
{
Debug.Log(request.error);
}
else
{
Debug.Log("Time Logged! " + json);
}
}
According to the Docs I should have two arguments, the first being my URL and the second Being my Data.
As for the JSON I want to send I made this struct
[Serializable]
private struct PlayerRequestBody
{
public string firstName;
public string lastName;
public string email;
public bool marketing;
public float time;
}
Then, I'm using JsonUtiltiy.ToJson to turn my json variable into a JSON string, which seems to work.
All of this said, no matter what I change in the request, even typing the JSON string out manually escaped. It just sends a request body of an empty JSON object like this:
{}
So if we take a look at what the API receives the logs look like this:
[PUT] /api/new 01:44:25:13 {}
I'm sure it's something small but I just don't have enough experience with Unity or C# to find the issue (and I want to go to bed).
As for how this gets called, In one of my Scripts that manages the game I have a handler method that is subscribed to GameState changes, so when my GameState === GameState.Victory then I would run the handler. So the code for that, with bits removed for readability looks like this:
// ...
private void Awake()
{
GameManager.OnGameStateChanged += GameManager_OnGameStateChanged;
}
// ...
private void GameManager_OnGameStateChanged(GameState state)
{
if (state == GameState.Victory)
{
handleVictory();
}
}
That handleVictory method just runs StartCoroutine on the IEnumerator at the moment
Any ideas? Thanks in advance
So for anyone who ever somehow runs into this, the answer is... Next is weird.
I made another API using Express JS and boom instant data from the Player.
I don't have time to look into it but there must be something about Unitys UnityWebRequest that Next doesn't agree with. Long and short I'm gonna pull the API out of next and then move over my components to React and host it on a server less function :)

Display a document without authentification

I am currently developping a java/jee application using alfresco as ged and spring as a framework.I want to display a file in the navigator without authentification requirment.So how can i do that.By the way i have 2 modules in my project:Frontend and backend which are communicating via rest calls.From the backend i tried to pass the byte array of the object but unfortunately i recieved it as string so i can't work with it.So any suggestion to solve this issue?
public Map<String, Object> getCourrierDetails(String idCourrier) throws Exception {
Map<String, Object> courriersDetails = runtimeService.getVariables(idCourrier);
courriersDetails.put("idCourrier", idCourrier);
DocumentDaoImpl dao=new DocumentDaoImpl();
Document docCmis = (Document) dao.getDocument("workspace://SpacesStore/73871a36-9a6c-42c6-b3e3-7d68362fe9c0");
byte[] myByteArray = readContent(docCmis.getContentStream().getStream());
ByteArrayResource resource = new ByteArrayResource(myByteArray) {
#Override
public String getFilename() {
return docCmis.getContentStreamFileName();
}
};
System.out.println(resource.getFilename());
//courriersDetails.put("resources", myByteArray);
System.out.println(courriersDetails.get("resources")+" rrrr");
//courriersDetails.put("contentStream",docCmis.getContentStream().getStream());
return courriersDetails;
}
Assuming your front-end and back-end are custom and your back-end communicates with Alfresco, all you need to do is write a proxy that resides in your back-end.
The proxy can establish a session with Alfresco using a pre-configured "service account" that has access to the content. In this way, the person using your custom webapp does not use their own credentials to get the object from Alfresco. Instead, the service account is used and the web app streams that to the requester.
For example, in one of my projects I have an AssetService that uses CMIS to get the InputStream from content given its ID:
public InputStream download(String assetId) {
CmisObject obj = session.getObject(assetId);
Document doc = null;
if (obj.getBaseTypeId().equals(BaseTypeId.CMIS_DOCUMENT)) {
doc = (Document) obj;
}
return doc.getContentStream().getStream();
}
Then, my Controller just asks the service for the asset to get some info about it to make it easy to set some helpful headers, then it gets the input stream from the asset service and returns that:
#RequestMapping(value = "/api/asset/{assetId:.+}/download/{name}", method = RequestMethod.GET)
public ResponseEntity<InputStreamResource> downloadAsset(
#PathVariable("assetId") String assetId,
#PathVariable("name") String name) {
// get the asset so we can get some info about it
Asset asset = assetService.getAsset(assetId);
// set the http headers (mimetype and length at a minimum)
HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.setContentType(MediaType.parseMediaType(asset.getMimetype()));
httpHeaders.setContentLength(asset.getLength());
// get the content stream
InputStream inputStream = assetService.download(assetId);
InputStreamResource inputStreamResource = new InputStreamResource(inputStream);
return new ResponseEntity<InputStreamResource>(inputStreamResource, httpHeaders, HttpStatus.OK);
}
This example uses Spring MVC within a Spring Boot app but of course you could do something similar with a plain old servlet if you want.
One option is to write your own web script and set it up in a way that it allows guest access.
http://docs.alfresco.com/4.1/concepts/ws-authenticating.html
There's also an option to completely disable permission checking, which I have never tried, though.
https://community.alfresco.com/thread/175381-disabling-permission-checking

spring boot multiple database configuration with microsoft sql server

i've multiple databases under a single sql server database.
from application.properties file. i've configured to default schema in springboot.
now i would like to chage to another database with same url, usrname, pawd.
how can i changedo this ? when i give annotation over class with
#table (name = db2.dbo.tname)
it throws error saying,
unable to map this dboject in database 1
here's my configuration:
spring.datasource.url=jdbc:sqlserver://localhost:1433;databaseName=testdb;integratedSecurity=false;
spring.datasource.username=sa
spring.datasource.password=myPassword
spring.datasource.driverClassName=com.microsoft.sqlserver.jdbc.SQLServerConnection
spring.datasource.initialize=true
my application works with the default db i gave on application properties. but i've to connect to another database.
how can i resolve this?
You cannot use the regular spring properties to do that. Here's an example on how you can connect to TWO databases (Or more if you need):
First you have to disable the autoconfiguration that picks up just one DB:
#EnableAutoConfiguration(exclude = {DataSourceAutoConfiguration.class, HibernateJpaAutoConfiguration.class, DataSourceTransactionManagerAutoConfiguration.class})
And now you just have to provide your own configuration for JPA and Datasources:
#Configuration
#EnableJpaRepositories(entityManagerFactoryRef = "ds1EntityManagerFactory",
transactionManagerRef = "ds1TransactionManager",
basePackageClasses = Ds1Repository.class)
public class DataSource1Config {
#Bean
PlatformTransactionManager ds1TransactionManager() {
return new JpaTransactionManager(tfccgEntityManagerFactory().getObject());
}
#Bean
LocalContainerEntityManagerFactoryBean ds1EntityManagerFactory() {
HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
LocalContainerEntityManagerFactoryBean factoryBean = new LocalContainerEntityManagerFactoryBean();
factoryBean.setDataSource(ds1());
factoryBean.setJpaVendorAdapter(vendorAdapter);
factoryBean.setPackagesToScan(Ds1Entity.class.getPackage().getName());
factoryBean.getJpaPropertyMap().put("hibernate.dialect", dialect);
factoryBean.getJpaPropertyMap().put("hibernate.show_sql", showSQL);
factoryBean.getJpaPropertyMap().put("hibernate.globally_quoted_identifiers", quoteIdentifiers);
return factoryBean;
}
#Bean
DataSource ds1() {
BasicDataSource dataSource = new BasicDataSource();
dataSource.setUrl(url);
dataSource.setDriverClassName(driverClass);
dataSource.setUsername(username);
dataSource.setPassword(password);
dataSource.setTestOnBorrow(testOnBorrow);
dataSource.setMaxTotal(maxTotal);
dataSource.setInitialSize(initialSize);
dataSource.setMaxIdle(maxIdle);
return dataSource;
}
}
You can have a copy of this class for a ds2 datasource on which you'll have a second set of transactionManager entityManagerFactory and datasource and on which you'll enable JPA Repositories and Entity scan for different packages and name the beans with different names.
Then, If you need transaction isolation in a method you'll have to provide the transactionManager name since you'd have 2:
#Transactional(transactionManager = "ds1TransactionManager")

Having trouble grasping how to securely sign JWT with Private Key

I'm looking at this example here which refers to the javascript functionality of JWT
I am trying to use javasrcipt to sign a piece of data. However, it says I have to use a Private RSA Key and it doesn't allow you to use a public key.
My goal was once a form is submitted via PHP, call this javascript function and encrypt the data.
Pardon my ignorance, but how can you use a private RSA key in javascript and keep it private at the same time?
It appears that you have to give it a private key somehow and wouldn't that private key be visible to a user using simple developer tools in the web browser?
function _genJWS() {
var sHead = '{"alg":"RS256"}';
var sPayload = '{"data":"HI","exp":1300819380}';
var sPemPrvKey = document.form1.pemprvkey1.value;
var jws = new KJUR.jws.JWS();
var sResult = null;
try {
sResult = jws.generateJWSByP1PrvKey(sHead, sPayload, sPemPrvKey);
document.form1.jwsgenerated1.value = sResult;
} catch (ex) {
alert("Error: " + ex);
}
}
What your are looking for is not JWS (signed), but JWE (encrypted).
If you want to send secured data to a server using JWE, you must :
get the public key of the server
encrypt your data using this public key and produce a JWE
send your JWE to the server.
As far as I know, there is no javascript library able to produce JWE (I may be wrong, but I found nothing).

Breeze js AutoGeneratedKeyType is always 'none' with ODataConventionModelBuilder

I have a simple entityframework poco object
public partial class Location: Entity
{
[Key]
public int Id { get; set; }
public string Description { get; set; }
}
The baseClass Entity looks as follow
public abstract class Entity : IObjectState
{
[NotMapped]
public ObjectState ObjectState { get; set; }
}
I expose this object via a Odata service using the ODataConventionModelBuilder
var server = GlobalConfiguration.DefaultServer;
ODataModelBuilder builder = new ODataConventionModelBuilder();
builder.Namespace = "MyNameSpace.Models";
builder.EntitySet<Location>(typeof(Location).Name);
var model = builder.GetEdmModel();
config.Routes.MapODataServiceRoute("odata", "odata", model, new DefaultODataBatchHandler(server));
config.AddODataQueryFilter();
When i consume this service with Breeze js i get an error from breeze when i try to create an entity with manager.CreateEntity().
Cannot attach an object to an EntityManager without first setting its
key or setting its entityType 'AutoGeneratedKeyType' property to
something other than 'None'
When i query an entity and edit the data and save it. All is ok.
I am using angular in combination with breeze on the client and Asp.net webapi 2 in combination with an odatacontroller on the server with EntityFramework 6 as ORM.
Can someone tell me what i am doing wrong!!!
Microsoft's ODataConventionModelBuilder is very incomplete, and they are aware of it ( This applies to both OData WebApi v 2.1 and v 2.2). Along with a number of smaller issues, it does not support 'referentialConstraints' or any info on store generated keys. MS is aware of these issues, among others, and has said that some of them will be fixed in a new release sometime in October.
Until then you have a couple of options.
Use the ODataConventionBuilder but then update breeze's metadataStore after the metadata is fetched to 'fix' the missing or wrong metadata.
myMetadataStore.metadataFetched.subscribe(function(args) {
var ms = args.metadataStore;
var entityType = ms.getEntityType("Customer");
entityType.setProperties({ autoGeneratedKeyType: AutoGeneratedKeyType.Identity });
dp = entityType.getDataProperty("companyName");
dp.validators.push(Validator.maxLength({ maxLength: 40 }));
// etc...
});
Avoid fetching metadata from the server at all and just describe the metadata on the breeze client directly: (see: http://www.breezejs.com/documentation/metadata-by-hand)
Skip OData completely and use the Breeze WebApi implementation (see http://www.breezejs.com/documentation/aspnet-web-api). This has the advantage of being both the most complete and the most robust implementation of all of breeze's features. Most of the Entity Framework samples in breeze.js.samples are built with this.
In general, we REALLY recommend the last choice if it is available to you. Please read this (http://www.breezejs.com/documentation/odata-server) for more information.

Categories