Post Form data from extjs4.2 to Spring Controller - spring-mvc

Here is my extjs 4.2.1 data store :
Ext.define('APP.store.CompanyStore', {
extend : 'Ext.data.Store',
requires: 'APP.model.Company',
model : 'APP.model.Company',
proxy: {
type : 'ajax',
url : 'searchP.html',
actionMethods :{read:'POST'},
reader : {
type: 'json',
root: 'items'
}
}
Here is my action on Submit :
var pname = Ext.getCmp('pname ').getValue();
var SearchObj = Ext.getCmp('searchForm').getValues();
SearchObj.pname =pname;
var store = Ext.getStore('APP.store.CompanyStore');
store.load({
params:{
"SearchObj" :Ext.encode(SearchObj)
},
callback: function(records, operation, success) {
// the operation object
// contains all of the details of the load operation
console.log(records);
}
});
My problem :
The object is not getting mapped to the POJO defined at server side in my Spring controller.What may be the problem.
My Spring Controller:
#RequestMapping(value = "/searchP", method = RequestMethod.POST)
public #ResponseBody String searchP(#RequestBody Company company){
System.out.println("pname"+company.getPName()); //getting null.Not getting actual value.
return "item";
}

Related

React-Admin with .net .The response to 'getList' must be like { data : [{ id: 123, ...}, ...] }, but the received data items do not have an 'id' key

I have an ASP.NET Core Web API and a React client. I'm trying to build admin dashboard with React-Admin. My problem is when I receive the data from server, my object are with property Id (uppercase), then in console I'm getting an error
The response to 'getList' must be like { data : [{ id: 123, ...}, ...] }, but the received data items do not have an 'id' key
I tried making new test class with property id (lowercase) in my server and then the problem is gone.
How can I fix this issue?
This is my test class and its working.
public class CityModel
{
public string id { get; set; }
public string Name { get; set; }
}
[HttpGet("Cities")]
public CityModel[] GetCities()
{
var city1 = new CityModel()
{
id = "ahsxge",
Name = "Berlin"
};
var city2 = new CityModel()
{
id = "axhdagw",
Name = "London"
};
var list = new List<CityModel>();
list.Add(city1);
list.Add(city2);
Response.Headers.Add("Access-Control-Expose-Headers", "X-Total-Count");
Response.Headers.Add("X-Total-Count", list.Count.ToString());
return list.ToArray();
}
This is my component in react :
const AppAdmin = () => {
const jwt = localStorage.getItem("jwt");
const httpClient = (url, options = {}) => {
options.user = {
authenticated: true,
token: 'Bearer ' + jwt
};
return fetchUtils.fetchJson(url, options);
};
const dataProvider = jsonServerProvider('https://localhost:44366/api', httpClient);
dataProvider.getList('Cities/Cities', {
pagination: { page: 1, perPage: 15 },
sort: { field: 'Name', order: 'ASC' },
})
.then(response => console.log(response));
return (
<Admin dataProvider={dataProvider}>
<Resource name='Cities/Cities' list={CitiesList} />
</Admin>
)
}
export default AppAdmin
You can configure the json converter to use camelCase serialization int the ConfigureServices method in the Startup.cs file the following way:
services
.AddControllers()
.AddJsonOptions(opts =>
{
opts.JsonSerializerOptions.PropertyNamingPolicy = JsonNamingPolicy.CamelCase;
})
This way you can use PascalCase properties in your c# code (which you should do), but your client will recieve camelCase json properties.

GraphQL.NET: How to separate the root query into multiple parts

I currently have a small application which is using GraphQL to communicate with the .net core backend. I currently have one one root query as is mandatory for GraphQL and am looking for a way to break this up into multiple pieces for organization's sake. My Query looks as follows:
public class ReactToFactsQuery : ObjectGraphType
{
public ReactToFactsQuery(IArticleService articleService,
INewsItemService newsItemService)
{
Field<ArticleType>(
name: "article",
arguments: new QueryArguments(new QueryArgument<IntGraphType> { Name = "id" }),
resolve: context =>
{
var id = context.GetArgument<int>("id");
return articleService.Get(id);
}
);
Field<ListGraphType<ArticleType>>(
name: "articles",
arguments: new QueryArguments(new QueryArgument<IntGraphType>() { Name = "count" }),
resolve: context =>
{
var count = context.GetArgument<int?>("count");
if (count.HasValue)
{
return articleService.GetAll(count.Value);
}
else
{
return articleService.GetAll();
}
}
);
Field<ListGraphType<NewsItemType>>(
name: "newsItems",
arguments: new QueryArguments(
new QueryArgument<IntGraphType>() { Name = "count" },
new QueryArgument<IntGraphType>() { Name = "newsType" }),
resolve: context =>
{
var count = context.GetArgument<int?>("count");
var category = context.GetArgument<int>("newsType");
var newsType = (NewsType)category;
if (count.HasValue)
{
return newsItemService.GetMostRecent(newsType, count.Value);
}
else
{
return newsItemService.GetMostRecent(newsType);
}
}
);
}
}
Currently the query is pretty small and manageable but as the application grows, I can easily see there being a huge number of queries defined in this class. THe current query names that exist are article, articles, and newsItems. Preferably, I'd like to create a query class to represent each model type (i.e one query class for article related queries, one for news item related queries, etc).
I've read the documentation here however I for whatever reason am struggling to understand the example here and how to apply it to my code.
All help is appreciated.
As the documentation says, you can split queries into virtual groups like this ...
Creating sub query types (ArticlesQueryType) that controls the specific queries.
public class RootQuery : ObjectGraphType
{
public RootQuery()
{
Name = "RootQuery";
// defines the articles sub query and returns an empty anonymous type object
// whose only purpose is to allow making queries on the subtype (ArticlesQueryType)
Field<ArticlesQueryType>("articles", resolve: context => new {});
}
}
// defines the articles specific queries
public class ArticlesQueryType: ObjectGraphType
{
public ArticlesQueryType(IArticleService articleService)
{
Name = "ArticlesQuery";
Field<ArticleType>(
name: "article",
arguments: new QueryArguments(new QueryArgument<IntGraphType> { Name = "id" }),
resolve: context =>
{
var id = context.GetArgument<int>("id");
return articleService.Get(id);
});
}
}
GraphQL query type would be
type RootQuery {
articles: ArticlesQuery
news: NewsQuery
}
type ArticlesQuery {
article(id: ID): Article
articles: [Article]
}
...
On the other hand, if you don't want to change the query structure and has only one root that holds the specific queries, you can split the queries into partial classes for clarity ...
public partial class RootQuery: ObjectGraphType
{
private IArticleService ArticleService { get; }
public RootQuery()
{
Name = "RootQuery";
InitializeArticlesQueries()
}
}
and in another file (RootQuery_Articles.cs) for example
public partial class RootQuery
{
protected InitializeArticlesQuery()
{
Field<ArticleType>(
name: "article",
arguments: new QueryArguments(new QueryArgument<IntGraphType> { Name = "id" }),
resolve: context =>
{
var id = context.GetArgument<int>("id");
return articleService.Get(id);
});
}
}
This way, the GraphQL query type is
type RootQuery {
articles: [Article]
....
}

Invoking repo actions from multi-select

I've created an UI action using various guides (include Jeff Potts really great ones) successfully and it function exactly as expected - but I want to add that action to the multi-select tool as well. It has been really difficult finding much documentation.
Some things I've tried:
Tried to find out if there was an applicable actionGroup - which there doesn't seem to be.
Tried adding the multi-select tags to my share-config-custom.xml to define the item - it shows up, but I obviously can't seem to use the action ID to reference that action.
My next step was to try and create a js file with a registerAction function in it, which I am able to do and have it run (I can see the console.log dump) but I don't really have any idea how I would go about invoking my repo action from there).
How can I complete this task?
There is already function exist for invoking the repository custom action.This function is defined inside below file.
share-war\components\documentlibrary\actions.js
You can take reference of below code for invoking the repository action.
onActionSimpleRepoAction: function dlA_onActionSimpleRepoAction(record, owner)
{
//ACE-2470 : Clone: Clicking multiple times the simple Workflow approval menu item gives unexpected results.
if (owner.title.indexOf("_deactivated") == -1)
{
// Get action params
var params = this.getAction(record, owner).params,
displayName = record.displayName,
namedParams = ["function", "action", "success", "successMessage", "failure", "failureMessage", "async"],
repoActionParams = {};
for (var name in params)
{
if (params.hasOwnProperty(name) && !Alfresco.util.arrayContains(namedParams, name))
{
repoActionParams[name] = params[name];
}
}
//Deactivate action
var ownerTitle = owner.title;
owner.title = owner.title + "_deactivated";
var async = params.async ? "async=" + params.async : null;
// Prepare genericAction config
var config =
{
success:
{
event:
{
name: "metadataRefresh",
obj: record
}
},
failure:
{
message: this.msg(params.failureMessage, displayName),
fn: function showAction()
{
owner.title = ownerTitle;
},
scope: this
},
webscript:
{
method: Alfresco.util.Ajax.POST,
stem: Alfresco.constants.PROXY_URI + "api/",
name: "actionQueue",
queryString: async
},
config:
{
requestContentType: Alfresco.util.Ajax.JSON,
dataObj:
{
actionedUponNode: record.nodeRef,
actionDefinitionName: params.action,
parameterValues: repoActionParams
}
}
};
// Add configured success callbacks and messages if provided
if (YAHOO.lang.isFunction(this[params.success]))
{
config.success.callback =
{
fn: this[params.success],
obj: record,
scope: this
};
}
if (params.successMessage)
{
config.success.message = this.msg(params.successMessage, displayName);
}
// Acd configured failure callback and message if provided
if (YAHOO.lang.isFunction(this[params.failure]))
{
config.failure.callback =
{
fn: this[params.failure],
obj: record,
scope: this
};
}
if (params.failureMessage)
{
config.failure.message = this.msg(params.failureMessage, displayName);
}
// Execute the repo action
this.modules.actions.genericAction(config);
}
},

What is the issue with asp.net route

This is from asp.net 5 / mvc 6. I have two controller methods, each takes a single parameter and each returns a string. One method takes a string parameter and the other takes a simple object. The method that takes the string parameter does not work (the value for the incoming parameter is always null). The call that passes in the simple object does work. I am making the calls to these methods from inside an angular controller using the $http service. I must be doing something wrong that is very simple, but I don't see it.
Here is the code for the controller class:
[Route("api/[controller]")]
public class ValuesController : Controller
{
[HttpPost("PostWithStringParam")]
public string PostWithStringParam([FromBody] string val)
{
return val ?? "<null>";
}
[HttpPost("PostWithInputparam")]
public string PostWithInputParam([FromBody] TestInputClass val)
{
string ret = "<null>";
if (val != null)
{
ret = $"First Name: {val.Name}, City: {val.City}";
}
return ret;
}
}
Here is the relevant code from the angular controller. Note the the "go" function is wired up to ng-click from a button.
vm.inputObject = {
name: "George",
city: "Chicago"
}
vm.inputString = "some data";
var callApi = function(url, data) {
$http({
method: "POST",
url: url,
data: data
}).then(
function (result) {
alert(result.data);
},
function (error) {
alert(error.status);
}
);
}
var callStringApi = function() {
var url = "api/values/PostWithStringParam";
callApi(url, vm.inputString);
}
var callObjectApi = function () {
var url = "api/values/PostWithInputParam";
callApi(url, vm.inputObject);
}
vm.go = function() {
callStringApi();
callObjectApi();
}
Can someone please tell me why the method that takes the input string doesn't work??
Thanks!
You need to strinfigy the data and specify the contentType as application/json when sending data. The default model binder will be able to map the posted data then.
var callApi = function(url, data) {
$http({
method: "POST",
url: url,
data: JSON.stringify(data),
contentType:"application/json"
}).then(
function (result) {
alert(result.data);
},
function (error) {
alert(error.status);
}
);
}

Calling a specific method in my Web API controller

So I'm trying to make a call to this specific method:
[HttpGet]
public int GetLogin(string u, string p)
{
UserLogin uL = new UserLogin();
return (int)uL.Authenticate(u, p);
}
However it keeps calling this method in my Controller instead:
public IEnumerable<string> Get()
{
return new string[] { "value1", "value2" };
}
^^ Which is the generated code in the Controller.
Here Angular code for my factory and, more importantly, my URI:
var loginFactory = angular.module('loginService', ['ngResource'])
loginFactory.factory('UserLogin', function ($resource) {
return $resource('api/login?:username?:password', {}, {
query: {
method: 'GET',
params: { username: 'hunter', password: 'hunter' },
isArray:true
}
});
});
Any insight would be much appreciated. Thanks.
Change your resource to this:
$resource('api/GetLogin?u=:username&p=:password', {}, { // if that's the right route
query: {
method: 'GET',
params: { username: 'hunter', password: 'hunter' },
isArray:true
}
});
Is your request going like api/login?username=something&password=something...?
if yes, the parameter names on the action should match the query string parameter names:
public int GetLogin(string **username**, string **password**)

Resources