PDF form submission to .Net Core Web API, return result - status

I have created a .net core web api controller in C#, that accepts PDF form data in FDF format, from a submit button on the form.
Because my controller tries to store the data in a database, I would like to return a success/fail status to the form, which should be displayed to the user.
The form is a regular Acrobat form (so not a web form) and is filled from the browser.
I have read about returning FDF data with a /Status, but have not found how to translate that info to web api, which is quite new to me.

You can Return a PdfResult that Adobe will accept. The return value must be based on where the document was submitted from. Here's my mvc controller
[AllowAnonymous]
[HttpPost]
public PdfResult SubmitForm(string Browser)
{
using (var sr = new StreamReader(Request.InputStream))
{
var fdfStream = sr.ReadToEnd();
var fieldsDict = _pdfFormService.ExtractFieldsText(fdfStream);
var formJson = JsonConvert.SerializeObject(fieldsDict);
var clientId = fieldsDict["client-id"];
var agencyId = fieldsDict["agency-id"];
var username = fieldsDict["username"];
var formId = fieldsDict["form-id"];
_pdfFormService.SubmitForm(int.Parse(agencyId), username, int.Parse(clientId), int.Parse(formId), formJson);
var document = PdfHelper.BuildSuccessPdf();
if (Browser == "Browser")
return document.ExportAsActionResult("success.pdf", HttpContext.ApplicationInstance.Response, HttpReadType.Open);
else
return document.ExportAsActionResult("success.pdf", HttpContext.ApplicationInstance.Response, HttpReadType.Save);
}
}
I found the definitions for PDF results and the document.ExportAsActionResult extension methods here.

Related

Try to access Request Form Post data from ActionFilterAttribute throw A potentially dangerous Request.Form value was detected from the client

I have implemented custom ActionFilterAttribute to create custom web access log and OnActionExecuted I try to access ActionExecutedContext.HttpContext.Request.Formcollection using Request.Form.GetValues("key") i get this error:
A potentially dangerous Request.Form value was detected from the
client (Aplications[0].Name="...."
because in my submitted form inputs contains HTML code.
I don't want to disable some .net MVC integrated security using validateRequest="false" and also I can't set to all my input or actions [AllowHtml] or ValidateInput(false) because my action filter catch all my controllers.
I found a hack solution but is no other option?
using (var reader = new StreamReader(request.InputStream))
{
var content = reader.ReadToEnd();
var inputsNameValueCollection = HttpUtility.UrlDecode(content).Split('&');
foreach (string input in inputsNameValueCollection)
{
var inputNameValue = input.Split('=');
var inputName = nameValue[0];
var inputValue = nameValue[1];
}
}

How do I pass JObject from Fiddler to Web Api?

I have function using JObject as parameter. Like this:
public void AddDevice(JObject jsonData)
{
dynamic json = jsonData;
JObject juser = json.User;
string login = json.UserLogin;
var user = juser.ToObject<User>();
//some operations on user and login
}
The question is: how do I pass do web api test user and login from Fiddler? Method is HttpPost type of course.
#edit
Im not asking how do I use Fiddler, I am asking how do I write correctly Body Request for JObject.

How to consume a secure Rest MVC web api

I'm just a beginner on the .NET world and I've created a web api (.NET 4.5.2) and I'm using the annotation [Authorize] above my controllers like shown below:
[Authorize]
public class PhasesController : ApiController
{
private TestReportEntities db = new TestReportEntities();
// GET: api/Phases
public IQueryable<Phase> GetPhase()
{
return db.Phase;
}
}
I've already created my DB and I'm using the default tables that the web.api uses to manage the access, as you can see on this image:
My tables
I've already done a method to request to my web api, in another project/solution, it's working fine when I remove the annotation [Authorize] from my web api controllers.
this is an example about how I'm requesting my api:
public int GetCurrentIdPhase(int idProject)
{
int phaseId = -1;
WebRequest request = WebRequest.Create(string.Concat(URL, string.Format("api/phases/?idProject={0}", idProject)));
using (var resp = (HttpWebResponse)request.GetResponse())
{
using (var reader = new StreamReader(resp.GetResponseStream()))
{
string objText = reader.ReadToEnd();
var phase = JsonConvert.DeserializeObject<List<Phase>>(objText);
phaseId = phase[0].id;
}
}
if (phaseId != -1)
{
return phaseId;
}
else
{
throw new Exception("Phase not found");
}
}
At the end of the day my questions are:
How can I request a token to my api (POST - www.myApi/token) using the example above?
How can I use the token, once I've got it, on every request to my API?
if you can help me I would really appreciate it.
Thanks.
I've created a method to get the Token from my Web API, this is the method:
var request = (HttpWebRequest)WebRequest.Create(string.Concat(URL, "token"));
var postData = "grant_type=password";
postData += string.Format("&userName={0}", user);
postData += string.Format("&password={0}", pass);
var data = Encoding.ASCII.GetBytes(postData);
request.Method = "POST";
request.ContentType = "application/x-www-form-urlencoded";
request.ContentLength = data.Length;
using (var stream = request.GetRequestStream())
{
stream.Write(data, 0, data.Length);
}
var response = (HttpWebResponse)request.GetResponse();
string objText = new StreamReader(response.GetResponseStream()).ReadToEnd();
var requestedToken = (JObject)JsonConvert.DeserializeObject(objText);
token = string.Concat(token, requestedToken["access_token"].Value<string>());
And to request something to my API all I need to do is just add the token on the header of all requests like shown on the line below:
request.Headers.Add(HttpRequestHeader.Authorization, getToke());
Hope it can help someone else who is beginning to work with .NET web API like me.
Regards.
Im assuming the "GetCurrentIdPhase" call is from an unrelated app with unrealted auth - if any auth.
The difficulty here is in using Authorize and the traidtional browser authentication flow. Here's an example of changing the pipeline a bit to use a different auth form for using console/desktop apps. You don't say where you are calling GetCurrentIdPhase from so I'll have to assume either a separate app. If its a web app and you are authenticated using the same tables, then you will have to share the token between them using for ex. the url blackice provided above.
If the app is a desktop/console/etc (not another app that the user had to auth against the same tables) then you can try this approach to change how auth is done to make it easier to access.
MVC WebAPI authentication from Windows Forms

Set default Media Formatter for a WebAPI action

I have implemented a custom media formatter and it works great when the client specifically requests "csv" format.
I have tested my api controller with this code:
HttpClient client = new HttpClient();
// Add the Accept header
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("text/csv"));
However, when I open the same URL from a web browser it returns JSON not CSV. This is probably due to standard ASP.NET WebAPI configuration that sets JSON as the default media formatter unless otherwise specified by the caller. I want this default behavior on every other web service I have but NOT on this single operation that returns CSV. I want the default media handler to be the CSV handler that I implemented. How do I configure the Controller's endpoint such that it returns CSV by default and only returns JSON/XML if requested by the client?
Which version of Web API are you using?
If you are using 5.0 version, you could use the new IHttpActionResult based logic like below:
public IHttpActionResult Get()
{
MyData someData = new MyData();
// creating a new list here as I would like CSVFormatter to come first. This way the DefaultContentNegotiator
// will behave as before where it can consider CSVFormatter to be the default one.
List<MediaTypeFormatter> respFormatters = new List<MediaTypeFormatter>();
respFormatters.Add(new MyCsvFormatter());
respFormatters.AddRange(Configuration.Formatters);
return new NegotiatedContentResult<MyData>(HttpStatusCode.OK, someData,
Configuration.Services.GetContentNegotiator(), Request, respFormatters);
}
If you are using 4.0 version of Web API, then you could the following:
public HttpResponseMessage Get()
{
MyData someData = new MyData();
HttpResponseMessage response = new HttpResponseMessage();
List<MediaTypeFormatter> respFormatters = new List<MediaTypeFormatter>();
respFormatters.Add(new MyCsvFormatter());
respFormatters.AddRange(Configuration.Formatters);
IContentNegotiator negotiator = Configuration.Services.GetContentNegotiator();
ContentNegotiationResult negotiationResult = negotiator.Negotiate(typeof(MyData), Request, respFormatters);
if (negotiationResult.Formatter == null)
{
response.StatusCode = HttpStatusCode.NotAcceptable;
return response;
}
response.Content = new ObjectContent<MyData>(someData, negotiationResult.Formatter, negotiationResult.MediaType);
return response;
}

Reading the results of me/accounts

I'm using the Facebook API for .NET, and need the access token for a page I'm the admin for.
I'm making the following call:
FacebookClient client = new FacebookClient(tokens["access_token"]);
JsonObject jsonResponse = client.Get("me/accounts") as JsonObject;
Does anyone have a piece of script to read the values into a List or Dictionary for easy consumption?
I figured it out eventually, this is the sample code in case anyone is interested. In this example, I'm retrieving the access_token field from the Page name set in the web.config
FacebookClient client = new FacebookClient(AccessToken);
JsonObject jsonResponse = client.Get("me/accounts") as JsonObject;
foreach (var account in (JsonArray)jsonResponse["data"])
{
string accountName = (string)(((JsonObject)account)["name"]);
if (accountName == ConfigurationManager.AppSettings["FacebookPageName"])
{
HttpContext.Current.Session["PageAccessToken"] = (string)(((JsonObject)account)["access_token"]);
break;
}
}

Resources