Read parameter in ActionFilterAttribute that is not present in action's prototype - asp.net-core-2.0

I am sending a form using Ajax, it has two inputs.
The receiving action only needs to consume one of the passed values.
An ActionFilterAttribute needs to consume the other argument.
For this reason, I wrote my action as
[AttributeImWriting]
public ContentResult Get(Guid value0) //[...]
but in my action filter when I try to do
context.ActionArguments["value1"]
I get an exception because the argument does not exist.
System.Collections.Generic.KeyNotFoundException: 'The given key 'value1' was not present in the dictionary.'
If I change the action's prototype to
public ContentResult Get(Guid value0, string value1) //[...]
Then I can read value1 from my filterAttribute.
So the question is: In an ActionFilterAttribute, how can I read an argument that was sent by a form, but which is not present in the prototype of the action on which the filter is applied?
I also tried using RouteData.Values but it didn't work any better.

If you are using POST to send values to controller side , in custom ActionFilterAttribute , you can get the parameters from Form property :
var value1 = context.HttpContext.Request.Form["value1"].ToString();
If you are using Get to send values to controller side , you can get the parameters from QueryString property ,then split and get each item:
var querystring = context.HttpContext.Request.QueryString;

Related

JQuery FileDrop.js How To Read Data Params in Controller?

Using ASP.NET MVC 5, I'm having trouble reading the param data I am sending from my filedrop jquery code into my controller.
Here is my .cshtml filedrop code:
And here is my Controller code, showing that param1 is being passed as null:
You can try defining a variable that will hold that the value of attribute. like this
var idValue = $('id').val();
And then pass this variable to the data.
data: { params: idValue }

JHipster: jhi-alert-error element and server side form validation?

I am using JHipster 3.3. In the generated "entity"-dialog.html, I noticed the tag jhi-alert-error element will display server validation error so for example if a field is mandatory as specified in entity JPA class like
#NotNull
private String name;
Then error message for that field will be returned after clicking the Submit button if value of the field is empty.
So questions:
How is jhi-alert-error implemented? I can't seem to see its implementation
I tried tweaking JPA annotation to make a field unique BUT this time no error message will be displayed in jhi-alert-error if I break the unique constraint by adding 2 records having the same value for the field,
E.g.
// note 'unique=true' below
#NotNull
#Column(name = "name", unique=true)
private String name;
or
#Table(name="Module", uniqueConstraints = #UniqueConstraint(columnNames = "Name"))
public Class Module implements Serializable { ...
So how would I go about implementing my own server side form validation so error messages will be displayed in jhi-alert-error when the unique constraint of a field is broken after clicking the Submit button?
Thanks in advance,
I'm using a slightly older version of jhipster (2.26), so there could be some differences in the code. To answer your first question the jhi-alert-error is a custom Angular directive, have a look at the alert.directive.js file and the jhAlertError directive (should appear after the jhAlert directive). The directive expects the httpResponse.data object to be the ErrorDTO server side object.
To add custom error messages, you need to return an ErrorDTO object and the directive will display the message. To do this you need to throw an exception and ensure that the spring AOP - ExceptionTranslator is configured to catch it. If you don't want to create new custom Exceptions, you can use the CustomParameterizedException:
#RequestMapping(value = "/pizzas",
method = RequestMethod.POST,
produces = MediaType.APPLICATION_JSON_VALUE)
#Timed
public ResponseEntity<Pizza> create(#RequestBody Pizza pizza) throws URISyntaxException {
if(pizza.isDisgusting()){
throw new CustomParameterizedException("Sorry, your pizza recipe is horrible");
}
log.debug("REST request to save Pizza : {}", pizza);
if (pizza.getId() != null) {
return ResponseEntity.badRequest().header("Failure", "A new pizza cannot already have an ID").body(null);
}
Pizza result = pizzaRepository.save(pizza);
return ResponseEntity.created(new URI("/api/pizzas/" + pizza.getId())).body(result);
}

add/read parameters to/from the url

If I add parameters to the url in the Objective-C code, is it possible to read it from the client?
Example:
- (NSURL *)serverURL {
return [NSURL URLWithString:#"http://rap.eclipsesource.com/demo?parametername=value"];
}
In the Client-JavaCode I can get the value of the parameter like this:
String parameter = RWT.getRequest().getParameter("parametername");
If I access the "app" with the browser I get a value for the parameter. If I access the app with the TabrisClient the value is null.
Is there a way to get the value also in the TabrisClient?
Update:
The server does not directly extract the query string from the request URL, but from the first JSON message received from the client. The web client provides the parameter queryString in the head part of the first UI request. Example:
{
"head": {
"queryString": "foo=23&bar=42",
"requestCounter": ...
},
"operations": [
...
]
}
You would have to fake this behavior in your Tabris client. I'd suggest that you file an issue against Tabris to provide API to set startup parameters.
Original answer:
If you're going to hard-code the parameter in the tabris client anyway, you could set the variable based on the connected client:
parameter = (RWT.getClient() instanceof WebClient)
? RWT.getRequest.getParameter("parametername")
: "tabris-value";
BTW, access to request parameters is going to change in RAP 3.0. Instead of RWT.getRequest().getParameter(), a ClientService will provide the parameters.

How would you implement a partial request & response, like the youtube api, using ServiceStack?

In the Youtube API, there is the power to request a "partial feed".
This allows the app developer to tailor the size and sturcture of the data returned, by specifying which "fields" to return.
i.e. GET api/person/1?fields=(id,email) would return a DTO containing only the id and the email fields, not the whole person response.
How would you attempt this using ServiceStack? Is there some way to attach a callback to the serialiser to control which properties to include in the response object?
From my experience servicestack only returns fields that actually has data. If my experience is correct then all you would need to do is figure out the best way to architect the request so that it is asking for specific data to return, this way you would only populate the response with data requested thus servicestack would only return that.
I implemented this for an API that only returns JSON.
First I created two structs to (de)serialize and interpret the "fields" query argument recursive syntax:
FieldSelector, which specifies a field and possibly its children FieldSelection enclosed between parenthesis;
FieldsSelection, which is a comma-separated list of FieldSelector.
I've used structs instead of classes because, AFAIK, you can't override class (de)serialization from/to URLs in ServiceStack. With structs you can do it by overriding ToString (serializer) and providing a constructor accepting a string as parameter (deserializer).
Then you include this on every request DTO that returns JSON:
FieldsSelection Fields { get; set; }
On a custom ServiceRunner<T>.OnAfterExecute you serialize the response DTO to JSON, parse it with ServiceStack.Text's JsonObject and apply the fields selection recursively with a method like this:
private static JsonObject Apply(this JsonObject json, FieldsSelection fieldMask)
{
IEnumerable<string> keysToRemove = json.Keys.ToList().Except(fieldMask.Keys);
foreach (var key in keysToRemove)
json.Remove(key);
foreach (var selector in fieldMask.Selectors.Values.Where(s => s.HasSubFieldsSelection))
{
var field = json[selector.Field];
if (field == null)
continue;
switch (field[0])
{
case '{':
json[selector.Field] = Apply(json.Object(selector.Field), selector.SubFieldsSelection).ToJson();
break;
case '[':
var itensArray = json.ArrayObjects(selector.Field);
for (int i = 0; i < itensArray.Count; i++)
itensArray[i] = Apply(itensArray[i], selector.SubFieldsSelection);
json[selector.Field] = itensArray.ToJson();
break;
default:
throw new ArgumentException("Selection incompatible with object structure");
}
}
return json;
}
Then you return the result as your response DTO. I've also implemented negative fields selectors (fields=-foo selects all DTO fields except foo), but you get the idea.
Look at ServiceStack.Text.JsConfig properties, they have all the hooks and customizations ServiceStack's text serializers support. Specifically the hooks that allow you to custom deserialization are:
JsConfig<T>.DeserializeFn
JsConfig<T>.RawDeSerializeFn
JsConfig<T>.OnDeserializedFn
We were able to implement said filtering by adding custom service runner and using some reflection in it to construct ExpandoObject with required field set by response DTO. See this for more info on service runners.

servicestack Razor view with request and response DTO

I'm having a go with the razor functionality in service stack.
I have a razor cshtml view working for one of my response DTO's.
I need to access some values from the request DTO in the razor view that have been filled in from some fields from the REST route, so i can construct a url to put into the response html page and also label some form labels.
Is there anyway of doing this? I don't want to duplicate the property from the request DTO into the response DTO just for this html view. Because i'm trying to emulate an existing REST service of another product, i do not want to emit extra data just for the html view.
eg
http://localhost/rest/{Name}/details/{Id}
eg
#inherits ViewPage<DetailsResponse>
#{
ViewBag.Title = "todo title";
Layout = "HtmlReport";
}
this needs to come from the request dto NOT #Model
link to user
link to user details
If you want to access the Request DTO it needs to be referenced by either by adding the Request to the Response DTO (which you don't want to do), so the other option is to add it to the IHttpRequest.Items Dictionary which is the preferred way to pass data between your filters and services.
public class MyService : Service {
public object Any(MyRequest request) {
base.Request.Items["RequestDto"] = request;
return MyResponse { ... };
}
}
Then in your view:
#{
var myRequest = (MyRequest)base.Request.Items["RequestDto"];
}
Wrapping Re-usable functionality in Request Filters
If you find you need to access the Request DTO in your views a lot, then rather than manually assigning it in each service, you can create a Request Filter Attribute or if you want it assigned all the time in a Global Request Filter.
public class SetRequestDtoAttribute : RequestFilterAttribute {
public override void Execute(
IHttpRequest req, IHttpResponse res, object requestDto)
{
req.Items["RequestDto"] = requestDto;
}
}
Then you can add this behavior by decorating the [SetRequestDto] attribute on different levels of granularity on either an Action, Service, Request DTO or base class.

Resources