ServiceStack PostFIleWithRequest "has" hard coded content-disposition name field - upload

I have an issue with the PostFileWithRequest<> method in ServiceStack in that the name of the file field is hard coded to the word "upload">
Part of the data stream
Content-Disposition: form-data;name="upload";filename="Julie.mp3"
And this is from line 407 in the file ServiceClientBase.cs
stream.Write("Content-Disposition: form-data;name=\"{0}\";filename=\"{1}\"{2}{3}".FormatWith(new object[] { "upload", fileName, text, text }));
This is contained in a virtual method but I do not know how I can change that in a derived class as there are other methods that are not accessible to my new class.
public virtual TResponse PostFileWithRequest<TResponse>(string relativeOrAbsoluteUrl, Stream fileToUpload, string fileName, object request)
Any ideas?
This look like a bug to me as the name of the form-data;name should be configurable and not hard coded.
In my case I need the file to be in a name called "File" in order to use a specific API.
Chris

I submitted a pull request to ServiceStack (albeit v4) which has been accepted and will be included in the next version 4.0.14.
This adds an optional parameter of fieldName to the PostFileWithRequest<TResponse> method which allows you to specify the field name instead of being stuck with upload.
So the new signature of the method:
public virtual TResponse PostFileWithRequest<TResponse>(string relativeOrAbsoluteUrl, Stream fileToUpload, string fileName, object request, string fieldName = "upload")

Related

.Net MVC returning a File

I'm working a Controller that will generate/retrieve files. These will optionally set headers.
public IActionResult SampleFileReport()
{
I see the return type is IActionResult (a data contract). I see inside the function I can still set
response.ContentType
Is there a preferred pattern for how to set ContentType in a controller?
I'm thinking it should be part of the DataContract and setting response.contentype is an anti-pattern, however I see examples such as this that utilize it. Returning a file to View/Download in ASP.NET MVC
All you need to do is return File:
public IActionResult SampleFileReport()
{
// do stuff
return File(bytes, mimetype, filename);
}
File also has overloads that accept Stream and string (path and filename to a file on the filesystem) in addition to byte[]. The mimetype is your content type, e.g. application/pdf, application/vnd.openxmlformats-officedocument.spreadsheetml.sheet (Excel), etc. The final filename param is optional. If it's provided, a Content-Disposition: attachment header is sent with the response, which prompts the browser to pop a download dialog. Otherwise, the default Content-Disposition: inline is used, and the browser will try to load the returned file directly the browser tab/window, assuming the mime-type is supported for native rendering the browser. If not, then you'll get a download dialog, regardless.
If we are talking about MVC (not .NET Core) then you can change IActionResult to FileContentResult
public FileContentResult SampleFileReport()
{
byte[] fileBytes = GetFileBytes();
return File(fileBytes, MediaTypeNames.Application.Octet, "fileName");
}
Just checked this class still exists. FileContentResult .NET Core

How to get image bytes or URL using its GUID?

Working with Kentico 11.0.26 CMS and a MVC website.
Have a custom content-only page type with an image field. After the image is uploaded on a page I need to display it on MVC site. But Kentico's generated code MyPageTypeProvider.GetMyPageType((int nodeId, string cultureName, string siteName) returns a page object that only contains the GUID of the image. No bytes, no URL.
How do I get the bytes or the URL of the uploaded image?
If you need the bytes, you can do this:
var attachment =DocumentHelper.GetAttachment(guid, SiteContext.CurrentSiteName, true);
var bytes = attachment.AttachmentBinary;
If you want a URL to the image, you can do something like this:
imageUrl = $"/getattachment/{guid}/attachment.aspx"
This documentation explains more ways to work with attachments.
You will need to either resolve the URL, or get file by GUID. Problem is, that Kentico Nuget API does not seem to provide enough options to get file binaries.
HelperMethods from Kentico.Content.Web.MVC NuGet seem to be good start:
https://github.com/Kentico/Mvc/tree/master/src/Kentico.Content.Web.Mvc
With these you can get file URL and use:
using (var client = new WebClient())
{
client.DownloadFile("http://example.com/file/song/a.mpeg", "a.mpeg");
}
Or you can write your own class or service, reference Kentico DLLs and use:
AttachmentBinaryHelper.GetFilePhysicalPath(string siteName, string guid, string extension)

Jenkins form validation with objects as parameters

I'm building a plugin for Jenkins and I'm trying to validate my form (connection test method). This worked fine when all #QueryParameter were Strings.
Now I'm trying to send my form validation method an Object like this:
public FormValidation doTestConnection(
#QueryParameter("url") final String url,
#QueryParameter("timeout") final String timeout,
#QueryParameter("bypassProxy") final boolean bypassProxy,
#QueryParameter("deployerCredentialsConfig") final CredentialsConfig deployerCredentialsConfig,
#QueryParameter("resolverCredentialsConfig") final CredentialsConfig resolverCredentialsConfig
) throws ServletException {
In my global.jelly file I have this:
<f:validateButton
title="${%Test Connection}" progress="${%Testing...}"
method="testConnection"
with="url,timeout,bypassProxy,deployerCredentialsConfig,resolverCredentialsConfig"/>
My CredentialConfig class implements Serializable but I guess that is not enough becuase I'm getting this when clicking the "Test Connection" button:
java.lang.IllegalArgumentException: Failed to invoke public hudson.util.FormValidation
org.jfrog.hudson.MyBuilder$DescriptorImpl.doTestConnection(java.lang.String,java.lang.String,boolean,org.jfrog.hudson.CredentialsConfig,org.jfrog.hudson.CredentialsConfig) throws javax.servlet.ServletException
Jenkins has no good documentation for using objects inside of FormValidation calls.
Looking at the Jenkins documentation and the code behind <f:validateButton/>, I believe it's impossible have objects bind in validation logic.
The docs say (https://wiki.jenkins-ci.org/display/JENKINS/Jelly+form+controls):
The 'with' attribute specifies the input fields sent to the server for
the validation. They are matched against the field attribute or the
name attribute of other input controls. The values of the nearest
input fields above the are sent to the server, so
this means the button has to come after the input fields. Multiple
fields can be specified by using ','.
The code simply gets fields by the names - there is no "object assembly" (I believe it's only done during actual config submission).
https://github.com/jenkinsci/jenkins/blob/96ec7a267e0efba2ec99590c871db0940e35920f/war/src/main/webapp/scripts/hudson-behavior.js#L2856
I bumped into a similar problem. Looking at the code, it seems stapler tries to convert your parameter to the type you provided in the doCheck function declaration.
class HandlerImpl extends AnnotationHandler<QueryParameter> {
public Object parse(StaplerRequest request, QueryParameter a, Class type, String parameterName) throws ServletException {
String name = a.value();
if(name.length()==0) name=parameterName;
if(name==null)
throw new IllegalArgumentException("Parameter name unavailable neither in the code nor in annotation");
String value = request.getParameter(name);
if(a.required() && value==null)
throw new ServletException("Required Query parameter "+name+" is missing");
if(a.fixEmpty() && value!=null && value.length()==0)
value = null;
return convert(type,value); // <--- HERE
}
}
As a workaround, I changed the type to boolean, like so:
public FormValidation doTestConnection(
#QueryParameter("url") final String url,
#QueryParameter("timeout") final String timeout,
#QueryParameter("bypassProxy") final boolean bypassProxy,
#QueryParameter("deployerCredentialsConfig") final boolean deployerCredentialsConfig,
#QueryParameter("resolverCredentialsConfig") final boolean resolverCredentialsConfig
) throws ServletException {
This allows me to at least check if the variable is set. It might not be enough for your use case, though.

Pass dynamic parameters in the keyvalue (message key) to package.properties

I have tried to pass dynamic parameters to keyvalue(message to display) which I will get from package.properties to the Action class through the getText() method. To get the message, we can use getText(String keyvalue) method. What should I do to pass some parameters and retrieve the parameters with the message through the getText() method?
I saw some API's to pass dynamic parameters. But I don't know how to use, these are the following API's, click here to see the Struts 2 API Documentation.
getText(String aTextName, List<Object> args)
getText(String key, String[] args)
getText(String key, String defaultValue, String[] args)
Thanks in advance..
I suppose that you have following properties in your package.properties
username.required=user name is required
password.required=password is required
you can use getText() as
getText("username.required")
getText("password.required")
Now if we want to use getText(String key, String[] args) we have to pass following parameters
aTextName - the resource bundle key that is to be searched for
args - a list args to be used in a MessageFormat message
That means the message format pattern and other static strings will, of course, be obtained from resource bundles. Other parameters will be dynamically determined at runtime.
example
we have following entry in resource file
disk.data=The disk \"{0}\" artist name is {1}.
in this {1} and {0} are the dynamic parameters and will be determined at run time so args will contain the value of these parameters.
String artistName= demo;
String diskName = "Artist";
String[] testArgs = {artistName, diskName};
So final call will be getText(disk.data, testArgs);
and it will show
The disk demo artist name is Artist.
Please go through MessageFormat to know how this work

Get body content using HttpServletRequest in Jersey

I am using Jersey 1.7 and I am trying to access the request body in my method very similar to this question:
How do I read POST parameters for a RESTful service using Jersey?
Body value comes in fine as email=xx#ws.com&password=test1
I tried using #Context HttpServletRequest request and tried to access the email with request.getParameter("email") but get nothing. There is nothing inside request.getparameterMap() either.
My API looks like this:
#POST
#Produces(...)
public Response getData(#FormParam("email") String email, #FormParam("password") String password, String body, #Context HttpServletRequest request) { ....
I tried changing the position of String body and request but to no avail.
The String body gets the value perfectly fine(it is coming from an iPhone device and not through a Form Submit and so shows up in the String body). Right now, I am trying to parse the body content(email=xx#ws.com&password=test1) and get each variable like email out but that is painful.
Is there some way to get the values using request.getParameter("email") ?
Or is there any quick utility to convert the body content into String email and String password ?
TIA,
Vijay
I never used form parameters myself, but the docs say it should work since forever:
#POST
#Consumes("application/x-www-form-urlencoded")
public void post(MultivaluedMap<String, String> formParams) {
// Store the message
}
http://wikis.sun.com/display/Jersey/Overview+of+JAX-RS+1.0+Features

Resources