I have a website served from a proprietary C++ server.
There is a standard javascript ajax function in the code but I don't want to start editing it.
The actual sending bit is as follows:
this.send=function(myawesomemodel)
{
/*Code redacted for brevity*/
obj.req.open('POST',myawesomeurl,true);
obj.req.setRequestHeader('Content-type','application/x-www-form-urlencoded');
obj.req.send(JSON.stringify(myawesomemodel));
}
It used to send key value pairs as a query string but now it needs to send json.
I can send this function a controller/action address (myawesomeurl) for the appropriate end point and I can send it an awesome object which will be accepted by the action as a basic C# Model (myawesomemodel):
public ActionResult myawesomeaction(MyAwesomeClass myawesomeclass)
{
}
For the .Net model:
public class MyAwesomeClass
{
public int A { get; set; }
public int B { get; set; }
public string C { get; set; }
}
How do I build a javascript object the controller will recognise please?
Here's my latest failure:
function MyAwesomeModel()
{
this.A=1;
this.B=2;
this.C='Three';
}
Then:
var anawesomemodel=new MyAwesomeModel();
myawesomeajaxmodel.send(anawesomemodel);
I cannot construct the correct object in plain javascript so the mvc action registers it, what's the correct method please?
var myawesomemodel = {
A : 1,
B : 2,
C : 'Three'
}
For anyone else with the same problem who finds this page, Stephen Muecke nailed it
Change the ajax object to:
this.send=function(myawesomemodel)
{
/*Code redacted for brevity*/
obj.req.open('POST',myawesomeurl,true);
obj.req.setRequestHeader('Content-type','application/json;charset=utf-8');
obj.req.send(JSON.stringify(myawesomemodel));
}
Related
In an Umbraco MVC partial view I have declared a parameter of type List, based on a custom model.
List<MyModel> modelList = new List<MyModel>();
public class MyModel{
public int ArticleID { get; set; }
public string ArticleName { get; set; }
public string ArticleType { get; set; }
public bool isSelected { get; set; }
}
That list get populated with data from another model before being rendered in a row.
On a button click even I want to take that list and loop through it, any rows which have been selected have to be added to another list, the problem is I can't seem to access it in a function on the same view.
Here's what I have at the moment, I'm fine with populating the other list so I just put an alert in and put a breakpoint on it to see what is in modelList, but I get the error "AddToList is not defined" and I think it's to do with how I'm trying to access the list.
Can anyone tell me how I should be doing this please?
function AddToList() {
$.each(#modelList, function () {
alert("function hit");
});
}
First you need to convert your server side model into javascript array, after that you can perform each operation on it.
function AddToList()
{
var data = #Html.Raw(Json.Encode(Model));
$.each(data, function () {
alert("function hit");
});
}
Im a beginner for automation testing.Here I want to get the data's from json to be used by selenium webdriver.I wrote one java class and hard coded something to get a result as a try.and getting an answer in console panel like
{
"name": "john",
"location": "jihu",
"job": [
{
"manager": [
{
"collegues": [
"ram",
"ranma",
],
}
}
}
(not exactly this).
Now i want to use this for one specific application using selenium webdriver. How can i move on with this.help me in detail.Thanks in advance.
From Selenium and Backend Comparison testing point of view i am answering the same .you need to parse json response using some Libraries like GSON , jackson etc into Java Pojo objects and then apply asserts on the fields you want to compare with json and UI. I guess you need to go through below topics first
1) Serialization -Deserialization API response
2) GSON or Jackson parsers
3) RestAssured ( Provides framework for API testing )
4) JAVA pojo classed and usage of them . you might need them to save your response in form of some Response class and compare objects .
You can use these online converters for converting a json object into Java Pojo Classes :
http://json2java.azurewebsites.net/ (I usually use this)
https://codebeautify.org/json-to-java-converter
and then place them in a package or in the same class as you wish :
You can better understand it by below example :
package com.demo.core;
import com.google.gson.Gson;
import io.restassured.RestAssured;
import io.restassured.response.Response;
public class Demo {
public static void main(String r[]) {
Response response1 = RestAssured.given().get("http://dummy.restapiexample.com/api/v1/employee/1"); // use your method to get the API response (I have used RestAssured here)
String json = response1.asString(); // you can use your json response here and convert it into a String
Gson gson = new Gson();
Employee emp = gson.fromJson(json, Employee.class); // The response is now captured in this Employee class
System.out.println(emp.getEmployeeAge());
System.out.println(emp.getEmployeeName());
System.out.println(emp.getEmployeeSalary());
}
}
class Employee {
private String id;
private String employee_name;
private String employee_salary;
private String employee_age;
private String profile_image;
public String getId() {
return this.id;
}
public void setId(String id) {
this.id = id;
}
public String getEmployeeName() {
return this.employee_name;
}
public void setEmployeeName(String employee_name) {
this.employee_name = employee_name;
}
public String getEmployeeSalary() {
return this.employee_salary;
}
public void setEmployeeSalary(String employee_salary) {
this.employee_salary = employee_salary;
}
public String getEmployeeAge() {
return this.employee_age;
}
public void setEmployeeAge(String employee_age) {
this.employee_age = employee_age;
}
public String getProfileImage() {
return this.profile_image;
}
public void setProfileImage(String profile_image) {
this.profile_image = profile_image;
}
}
You can easily assert the values after the response is captured in Java classes using their getter methods like I have used in the code to get field values present in Employee class.
Please do let me know if you still got an issue.
If your result contains many fields than better to shift all converted java classes into a separate package for a clear code.
I have an object as follows which is then stored in an array of them.
I would like to send the array of them to Web API, usually you would use JSON.stringify on an object, but would this work also being in an array?
I then need to work out what type of object they would be received as the other end as I need to iterate through them. I was hoping to use a typeof class.
var fieldarray = [];
$("div[class*=container_]").each(function (index) {
var firstElement = $(this).first();
var object = $(this).find('.object');
fielddata = {
id: firstElement.attr('class').match(/\d+/)[0],
attributes: [{
'label_text': firstElement.text(),
'label_width': firstElement.width(),
'label_height': firstElement.height(),
'label_color': firstElement.css('color'),
'Field_Width': object.width(),
'Field_Height': object.height,
'Field_Type': object.attr('Field_Type'),
'PositionX': firstElement.offset().left,
'PositionY': firstElement.offset().top,
'Field': firstElement.attr('class').match(/\d+/)[0],
'Label_Font': firstElement.css('font-family')
}]
}
array.push(fielddata);
});
Can I send this using JSON.stringify, and if so, what type would I receive this as in the Web API server side?
I usually use a public class type but the above code has an object inside an object - that is my problem.
I have sorted this now, basically I used:
[HttpPut]
public int Put(int id, [FromBody] FormData HTMLFORM)
{
....
}
and stored it in my type class as a string:
public class FormData
{
public int id { get; set; }
public string HTML { get; set; }
public string fieldData { get; set; }
}
I then used
IList<AttributeData> findingList = JsonConvert.DeserializeObject<IList<AttributeData>>(HTMLFORM.fieldData);
And it was stored in the list which I can iterate through using my type class of AttributeData!
Thanks
I am working on a Javascript multiplayer game and I need to send a Javascript object from one client to another client using signalR. Till now I am sending client to client data by string or array.
But I don't know how to receive Javascript object in server for sending that object to another client.
var MyInfo = {
UserName: loginUserName,
userid: logInUserId,
getinfo: function() {
return this.UserName + ' ' + this.userid;
}
}
Which data type shall I use to receive that Javascript data in my hub.
I am working on C# .NET MVC.
I got the answer of my problem...
C# language provides automatically conversion of Javascript object to Object data type. Thus I send the Javascript object to server and then receive that object in Object datatype. After that I send that object to destination client, as follow:
var MyInfo = {
UserName: loginUserName,
userid: logInUserId,
getinfo: function() {
return this.UserName + ' ' + this.userid;
}
};
var MyInfo2 = {
UserName: "",
userid: "",
getinfo: function() {
return this.UserName + ' ' + this.userid;
}
};
var chessR = $.connection.gameHub;
var myConnectionID;
chessR.client.testObject = function(temp) {
MyInfo2.UserName = temp.UserName;
MyInfo2.userid = temp.userid;
alert(MyInfo2.getinfo());
}
$.connection.hub.start().done(function() {
chessR.server.testObject(MyInfo);
});
On signalR hub I write:
public class GameHub : Hub
{
public void testObject(Object MyInfo)
{
Clients.Caller.testObject(MyInfo);
}
}
Now the problem solved.
I think the easy way to go would be creating a MyInfoModel on the server side containing the same properties of the JS model and simply pass it on the server method.
Normally, SignalR and ASP.NET should handle the serialization of your data, letting you to send and recieve complex objects. (Please note that I have not tested it, it is just an educated guess). Since you can easily send complex objects from the server to the client, I see no reason why you cannot send them from the client to the server.
If the first approach (creating the model on the server and make the server method accept a model) doesn't work, you can serialize the object, send it as a string and deserialize it on the hub (you still need the model to deserialize).
If neither of these work, leave a message and when I get to a computer with VS I will test them and share the results.
Hope this helps! Good luck!
Your solution is good for sending the object between JS clients, but if you want to use the object on the C# base Server or get some typing (usually ideal), then you can create a C# model that matches the JS object.
And depending on the signalr Json serialize casing options you use, you can use attributes to specify how the C# object should be de/serialized:
using System.ComponentModel.DataAnnotations;
using System.Text.Json.Serialization;
public class MyInfoModel
{
[Required]
[JsonPropertyName("userId")]
public string UserId { get; set; }
[Required]
[JsonPropertyName("userName")]
public string UserName { get; set; }
}
JS client side (in typescript)
type UserInfo = {
userName: string;
userId: string;
};
const myInfo: UserInfo = {
userName: loginUserName,
userId: logInUserId,
};
await $.hubConnection.send("HubMethodWithTypedParam", myInfo);
Now the hub method can be declared with a typed parameter like this:
public class GameHub : Hub
{
public void HubMethodWithTypedParam(MyInfoModel myInfo)
{
...
}
}
I'm working on a project using Breeze and I came across a problem with some entities I had created using a one-to-one relationship. This is a bit of a long story, but it has a happy ending, so bear with me :)
Here is a cut down version my C# code:
public class Person {
[Key]
public int Id { get; set; }
public virtual User User { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
}
public class User {
[Key]
public int Id { get; set; }
[Required]
public virtual Person Person { get; set; }
[Required]
public string EmailAddress { get; set; }
[Required]
public string Password { get; set; }
}
public class MyDbContext : DbContext {
public DbSet<Person> Person { get; set; }
public DbSet<User> User { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder) {
modelBuilder.Entity<User>().HasRequired(x => x.Person);
}
}
This creates a Persons database table with an auto generated primary key, and a Users table with a manually entered primary key, which is a subset of the Persons table.
I create these entities, and attempt to save them in my javascript code with something like:
var manager = new breeze.EntityManager('api/Db');
// other breeze initialization stuff, metadata etc.
var person=manager.createEntity('Person', undefined, breeze.EntityState.Detached);
var user=manager.createEntity('User', undefined, breeze.EntityState.Detached);
// set other fields, name, email, password
user.Person(user);
manager.addEntity(user);
manager.saveChanges().then(function() { // etc
When the SaveChanges function is called in my BreezeController I get this exception:
Validation error: Property: 'Person', Error: 'The Person field is required.'
Upon examination of the JSON that is send to the BreezeController I find that the Id of both the Person and the User was '-1', and that the JSON did not nest the Person entity inside the Person property of the User. So there was no way for the EFContextProvider to know that there was supposed to be a relationship between these objects.
My first attempt to solve this was to send the 'Person' entity to the backend with saveChanges, then send the 'User' in a seperate transaction. Eg:
manager.addEntity(person);
manager.saveChanges().then(function() {
user.Person(user); // this line moved from previous example,
// breeze throws error here
manager.addEntity(user);
manager.saveChanges().then(function() { // etc
Using this approach I got this error from breeze.js:
Cannot attach an object to an EntityManager without first setting its key
or setting its entityType 'AutoGeneratedKeyType' property to something other
than 'None' at checkEntityKey (http://localhost:12151/scripts/breeze.debug.js)
So I tried to set the key on the User to be the value filled in when the Person was saved. Using "user.Id(person.Id);" Now in the BreezeController I still get the same error:
Validation error: Property: 'Person', Error: 'The Person field is required.'
Next I tried to modify the SaveChanges method of my BreezeController to check for an incoming 'User' object which doesn't have a 'Person' property set, then Find the person in the database, and assign it to the Person before calling _efContextProvider.SaveChanges(saveBundle); I lost the code for exactly how I did this, but it's irrelevant as it didn't work properly either... It created a SECOND 'Person' in the database, exactly the same as the one that was saved in the first manager.saveChanges, but it had a new primary key generated. This did however successfully associate the second Person with the User.
After thinking about it overnight I came up with a working solution by subclassing the EFContextProvider with this:
public class MyEfContextProvider : EFContextProvider<MyDbContext>
{
protected override Dictionary<Type, List<EntityInfo>> BeforeSaveEntities(
Dictionary<Type, List<EntityInfo>> saveMap)
{
AssociateOneToOne(saveMap, typeof(Person), typeof(User));
return saveMap;
}
private static void AssociateOneToOne(IReadOnlyDictionary<Type,
List<EntityInfo>> saveMap, Type parent, Type child)
{
if (!(saveMap.ContainsKey(parent) && saveMap.ContainsKey(child))) return;
Func<EntityInfo, object> idFunc = delegate(EntityInfo info)
{
var o = info.Entity;
return o.GetType().GetProperty("Id").GetValue(o);
};
var childProp = child.GetProperty(parent.Name);
var childMap = saveMap[child].ToDictionary(idFunc, info => info.Entity);
var parentMap = saveMap[parent].ToDictionary(idFunc, info => info.Entity);
foreach (var childEntry in childMap)
{
childProp.SetValue(childEntry.Value, parentMap[childEntry.Key]);
}
}
}
Now I realise this has been a long question, and thanks for reading. But the only question I have is, why do I have to do it this way? Is this something that Breeze doesn't have implemented yet? If so, is the way I've done it ok?
You've uncovered a bug ... or so it seems to me. I have filed it and we'll let you know when it is fixed.
On a different note, your BreezeJS client code is a little more tortured than it needs to be. Why create an uninitialized detached entity ... and then add it?
The line user.Person(user); doesn't seem right at all. That should fail. I think you meant user.Person(person);. But you won't need that either.
Try this:
var manager = new breeze.EntityManager('api/Db');
// other initialization stuff.
// adds new, initialized Person entity
var person = manager.createEntity('Person', {
// perhaps init fields: firstName, lastName
});
// adds new, initialized User entity, associated w/ parent Person
var user = manager.createEntity('User', {
personId: person.Id(), // SETS THE KEY TO PARENT PERSON
// perhaps init fields: emailAddress, password (really!?!)
});
manager.saveChanges().then(function() { ... etc.
Update 8 May 2013
Yes, that commit is the fix on the BreezeJS side. We'll release it soon ... although of course you are free to grab an intermediate commit. I wouldn't ... because intermediate, untagged commits haven't been properly QA'd.
I think you will still have a problem ... this time on the EntityFramework side. 1-1 is pretty trick in Code First; you may want to look at this StackOverflow thread.
To be specific to your case, I think you need to change your definition of User to this:
public class User {
[Key]
[ForeignKey("Person")]
[DatabaseGenerated(DatabaseGeneratedOption.None)]
public int Id { get; set; }
//[Required]
public virtual Person Person { get; set; }
[Required]
public string EmailAddress { get; set; }
[Required]
public string Password { get; set; }
}
You shouldn't need the "Fluent API" mapping for User that you show above and it might get in the way.
// DELETE THIS !!!
protected override void OnModelCreating(DbModelBuilder modelBuilder) {
modelBuilder.Entity().HasRequired(x => x.Person);
}
FWIW, the Order/InternationalOrder relationship in DocCode is virtually the same as your Person/User. The test, "can save a new Northwind Order & InternationalOrder [1..(0,1) relationship]", in the saveNorthwindTests.js confirms the model definition and the Breeze fix.
Hope this helps.
Breeze v 1.3.3 is now available on the Breeze website and we did fix an issue with 1-1 mappings. Could you confirm whether this corrects your issue?