No response from web service when a POST is sent from client - asp.net

My web service uses asp.net web api. Currently my api controller doesn't do anything because I want to inspect the post to see what I'm working with here.
You'll notice that I'm posting to localhost. That's because currently I'm only running the service app in the debugger so that I can inspect the post via a Watch.
My problem is that it doesn't seem like my post is going anywhere. The breakpoint that I've set on the Post void never gets hit when I submit the form from the webpage.
Am I misunderstanding how this is supposed to work here?
Controller
public class CashbackController : ApiController
{
// POST api/<controller>
public void Post([FromBody]string value)
{
}
}
Client web page
<form action="http://localhost:49474/api/Cashback" method="post">
<p>
API Key: <input type="text" name="_apikey" /><br />
Receipt No: <input type="text" name="_receipt" /><br />
Purchase Date: <input type="text" name="_date" /><br />
Cashback Total: <input type="text" name="_cashback" />
</p>
</form>
<p><input type="submit" value="Submit" /></p>
<script>
$(document).ready(function() {
alert("JQuery works");
});
$("input[type=submit]").on("click", function () {
$("form").submit();
});
$("form").submit(function () {
$.post($(this).attr("action"), $(this).serialize(), function(data) {
if (!data.IsOK) {
alert("Error: " + data.Error);
}
else
{
alert("Post successful.");
}
return;
});
return false;
});
</script>
EDIT
Inspecting with fiddler, it doesn't look as though my clicking on the submit button is doing anything at all...
Correctly referenced jquery and fiddler caught this:
POST http://localhost:49474/api/Cashback HTTP/1.1
Host: localhost:49474
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:36.0) Gecko/20100101 Firefox/36.0
Accept: /
Accept-Language: en-GB,en;q=0.5
Accept-Encoding: gzip, deflate
DNT: 1
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
Referer: http://localhost/servicepost/
Content-Length: 85
Origin: http://localhost
Connection: keep-alive
Pragma: no-cache
Cache-Control: no-cache
_apikey=abcdefghijklmnopqrstuvwxyz&_receipt=1234567890&_date=2015-03-31&_cashback=100
However, in my controller, value is still null

Mkay so there were a few things wrong here...
First, I hadn't referenced the correct jquery source
NOTE: Only ever use the googleapis link(this one is to jquery 2.1.3.min) or another such link as you see fit. It's just simpler
Secondly, my controller wasn't accepting the correct type. Now this is where I really got confused because the client app isn't going to know what models my api uses.
Turns out it's just a matter of mirroring the model on the client app that posts to the api. So consider the following
public class UserController : ApiController
{
// POST api/<controller>
public void Post([FromBody]User Value)
{
}
}
public class User
{
public int ID { get; set; }
public string Username { get; set; }
public string EmailAddress { get; set; }
}
The form must post a mirror of the model which in this case would look something like this:
<form method="post" action="path-to-service/api/User">
<div>
Username: <input type="text" name="Username" /><br />
Email Address: <input type="text" name="EmailAddress" />
</div>
</form>
The ajax post above will work but will need to be modified to do exactly what you want it to. Typically I just throw in some error handling into at if statement and a redirect into the else.

Related

Problem invoking widget's action method in NopCommerce

I am trying to develop a widget in NopCommerce 4.3. I need to Post data from widget public view to the controller's Action method with Ajax. The problem is that when the call is made from the view, Product page is called instead of my widget view. This is the VS output:
Microsoft.AspNetCore.Hosting.Diagnostics: Information: Request starting HTTP/2.0 POST https://localhost:44331/aliento-de-ogro application/x-www-form-urlencoded 292298. Excepción producida: 'System.ArgumentException' en System.Private.CoreLib.dll. Microsoft.AspNetCore.Routing.EndpointMiddleware: Information: Executing endpoint 'Nop.Web.Controllers.ProductController.ProductDetails (Nop.Web)' Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker: Information: Route matched with {action = "ProductDetails", controller = "Product", area = ""}. Executing controller action with signature Microsoft.AspNetCore.Mvc.IActionResult ProductDetails(Int32, Int32) on controller Nop.Web.Controllers.ProductController (Nop.Web). Microsoft.AspNetCore.Mvc.ViewFeatures.ViewResultExecutor: Information: Executing ViewResult, running view ProductTemplate.Simple. Microsoft.AspNetCore.Mvc.ViewFeatures.ViewResultExecutor: Information: Executed ViewResult - view ProductTemplate.Simple executed in 411.9849ms.
This is how widget's view looks like:
<form id="AjaxForm" method="post">
<input type="hidden" id="productId" value=#ViewBag.sku />
<input type="hidden" id="input_elem" name="image" />
<div class="col-md-9">
<div id="ErrorAlert" class="alert alert-danger" style="display:none" role="alert">
Error en los datos enviados!
</div>
<div id="ExitoAlert" class="alert alert-success" style="display:none" role="alert">
Datos recibidos correctamente!
</div>
</div>
<button class="btn btn-success" id="SubmitBtn" type="submit">Save photo</button>
</form>
$.ajax({
type: "post", // Verbo HTTP
url: "#Url.Action("TakePhoto", "Photo")",
dataType: "application/json",
headers: { "RequestVerificationToken": $('input[name="__RequestVerificationToken: "]').val() },
data: JSON.stringify(
{
// Datos / Parámetros
ProductId: $("#productId").val(),
Role: role, //$("#role").val(),
ExpressionName: expressionName, //$("#expressionName").val(),
Photo: $("#photo").attr('src')
}),
contentType: "application/json; charset=utf-8"
})
.done(function (result) {
alert(result.Message);
}
})
.fail(function (xhr, status, error) {
})
.always(function () {
});
return false;
});
Asp.net backend is receiving "application/x-www-form-urlencoded" instead of "application/json". Why? Is this the reason because my widget's controller is not reached? Why Nop.Web.Controllers.ProductController.ProductDetails (Nop.Web)' is invoked?
It doesn't seem you're receiving the request from the Ajax call. Instead you're receiving the request from some form in the page.
This seems clear since you're receiving the request from a different endpoint and with a different content type. Since it seems you have an image in your form the multipart request is logical in that scenario.
My suggestions are:
Check your page and look for a multipart form in it. Some problem handling events could make that form to fire instead of your code. Are there nested forms?
Enable the request history in Chrome and the preserve log option. Get a verbatim copy of the request. Check the Url.
In .NET, retrieve a verbatim copy of the received request. Check the Url.
Set a breakpoint in your Javascript code and see if it is being called at all.
I think this will help you.

Button calling different servlet code in html form

I am bit new to Java web programming
I have two buttons(Test connection and Execute) in an html form and the form action is a servlet. How can I differentiate the action in the servlet based on which button is clicked.
Thanks
In the HTML:
<input type='submit' name='submitButton' value='Test connection' />
<input type='submit' name='submitButton' value='execute' />
In the servlet:
String clickedButtonValue = request.getParameter("submitButton");
if("Test connection".equals(clickedButtonValue))
{
...
}
else if("execute".equals(clickedButtonValue))
{
...
}
else ...
The reason this works: With both submit buttons sharing the same name attribute, the browser will only send the value of the one that was clicked.

Avoid ajax file upload attack

I have a form and in a HTML form inside which I have file upload button.
File is going to be uploaded using AJAX request.
On file upload I am checking extension and file size.
I am uploading file into /home/xyz/upload/username/username_timestamp
But since I am using AJAX request, I cannot(and don't want to) use the CAPTCHA and there is a risk of attacker flooding with files. How can I deal with this issue?
PS: I am using Spring-MVC(not spring security) and Struts2 in my projects, so framework specific solution will be icing on a cake.
Protect your action to be called out of expected by using Strut's token mechanism and your expected logic of file uploads inside your parent action (e.g. max uploads per minutes) ; something like below:
index.jsp
<form action="upload" method="post" enctype="multipart/form-data">
<label for="myFile">Upload your file</label>
<input type="file" name="myFile" />
<s:if test="uploadsPerMinutes < 10">
<s:token name="tknUpload" /> <!-- *** conditional generate token *** -->
</s:if>
<sj:submit value="Submit Form" targets="myAjaxTarget"/>
</form>
<div id="myAjaxTarget">
</div>
struts.xml
<action name="upload" class="com.upload.FileUpload">
<interceptor-ref name="tokenSession/>
<interceptor-ref name="basicStack"/>
<result name="success" type="stream">...</result>
</action>
<action name="uploadParent" class="com.upload.FileUploadParent">
<result name="success">index.jsp</result>
</action>
FileUploadParent.java
public class FileUploadParent extends ActionSupport{
...
public static int uploadsPerMinutes = 0;
private static DateTime lastUploadTime;
public String execute()
{
...
synchronized(uploadsPerMinutes){
if(currentTime - lastUploadTime > 1min) uploadsPerMinutes=0;
else uploadsPerMinutes++;
lastUploadTime = currentTime;
}
return SUCCESS;
}
public String getUploadsPerMinutes()
{
return uploadsPerMinutes;
}
}
With these, client have to get a token from server for each file upload. These are behind the scene and do not disturb your normal users.

Error uploading file from form-data to Spring Server

I am uploading a picture using form-data taking the picture from the Client's PC to Spring MVC Server.
Update Page:
<!DOCTYPE html >
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Spring MVC - Upload File</title>
</head>
<body>
<form id="form1" method="post" action="/upload" enctype="multipart/form-data" accept-charset="utf-8">
<!-- File input -->
<input name="file" id="file" type="file" /><br/>
<input type="submit" value="Upload" />
</form>
</body>
</html>
And this is the Spring Controller
#RequestMapping(value = "upload", method = RequestMethod.POST)
public #ResponseBody
String provaUpdate(MultipartHttpServletRequest request,Principal p,HttpServletResponse response)throws IOException {
String result="";
LocalFileManager mLocalFileManager = LocalFileManager.get();
Iterator<String> iterator = request.getFileNames();
while(iterator.hasNext())
{
System.out.println("iterator.next()="+iterator.next());
}
System.out.println("request.getFileMap().isEmpty()??"+request.getFileMap().isEmpty());
// mLocalFileManager.saveLocalData(g,g.getPicturesCount(), request.getFile("new").getInputStream());
return result;
}
So, when i run that, it just prints:
request.getFileMap().isEmpty()??true
Then, no Files seems to be uploaded, but if I get the request.getInputStream() I can write a TXT File showing that:
------WebKitFormBoundaryWG8vA5PuTFFxPBqK
Content-Disposition: form-data; name="file"; filename="1.jpg"
Content-Type: image/jpeg
�� JFIF ��ICC_PROFILE 蠠 mntrRGB XYZ ٠ $ acsp �� ӭ )𽞯򕮸B򤊃9
desc D ybXYZ bTRC Ԡ dmdd ࠠ ɧXYZ
h gTRC Ԡ lumi
| meas
//(Symbols) Long ETC, so the picture is sent !!
------WebKitFormBoundaryWG8vA5PuTFFxPBqK--
So, seems that the picture is sent correctly but the MultipartHttpServletRequest is not able to get the File.
Which is my mistake?
I think,you may be missing below entry in your spring configuration xml file.
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<!-- below properties can be configured as per your need -->
<property name="maxUploadSize" value="5000000" />
<property name="maxInMemorySize" value="5000000" />
</bean>
The mistake was that i am working with Thymeleaf, so the form is different.
It is solved changing that:
1- Create a class that contains a MultipartFile, like this:
public class Images {
MultipartFile image;
public MultipartFile getImage() {
return image;
}
public void setImage(MultipartFile image) {
this.image = image;
}
}
2- The correct form code for a Spring Server working with Thymeleaf:
<form id="myform" action="#" th:action="#{/upload}" th:object="${Images}" method="POST" modelAttribute="Images" enctype="multipart/form-data">
<input type="file" th:field="${Images.image}" name="file"/>
<input type="submit" value="Upload"/>
</form>
And finally the correct Controller method:
#RequestMapping(value = "upload", method = RequestMethod.POST)
public String addVocabularyValadate( #ModelAttribute("Images") Images images,BindingResult bindingResult,
Model model) throws IOException
{
System.out.println("inputstream Nombre!"+images.getImage().getOriginalFilename());
if(bindingResult.hasFieldErrors() == true)
return "error";
else
return "upload OK!";
}

ASP.Net MVC 4 Form with 2 submit buttons/actions

I have a form in ASP.Net and razor.
I need to have two ways of submitting said form: one that goes through the Edit action, and another that goes through the Validate action.
How should I go about doing this?
I don't mind using JavaScript for this.
EDIT:
Using the custom attribute I get this error.
The current request for action 'Resultados' on controller type 'InspecoesController' is ambiguous between the following action methods:
System.Web.Mvc.ActionResult Validar(System.Collections.Generic.ICollection1[Waveform.IEP.Intus.Server.Web.ViewModels.ResultadoViewModel]) on type Waveform.IEP.Intus.Server.Web.Controllers.InspecoesController
System.Web.Mvc.ActionResult Resultados(System.Collections.Generic.ICollection1[Waveform.IEP.Intus.Server.Web.ViewModels.ResultadoViewModel]) on type Waveform.IEP.Intus.Server.Web.Controllers.InspecoesController
That's what we have in our applications:
Attribute
public class HttpParamActionAttribute : ActionNameSelectorAttribute
{
public override bool IsValidName(ControllerContext controllerContext, string actionName, MethodInfo methodInfo)
{
if (actionName.Equals(methodInfo.Name, StringComparison.InvariantCultureIgnoreCase))
return true;
var request = controllerContext.RequestContext.HttpContext.Request;
return request[methodInfo.Name] != null;
}
}
Actions decorated with it:
[HttpParamAction]
public ActionResult Save(MyModel model)
{
// ...
}
[HttpParamAction]
public ActionResult Publish(MyModel model)
{
// ...
}
HTML/Razor
#using (#Html.BeginForm())
{
<!-- form content here -->
<input type="submit" name="Save" value="Save" />
<input type="submit" name="Publish" value="Publish" />
}
name attribute of submit button should match action/method name
This way you do not have to hard-code urls in javascript
You can do it with jquery, just put two methods to submit for to diffrent urls, for example with this form:
<form id="myForm">
<%-- form data inputs here ---%>
<button id="edit">Edit</button>
<button id="validate">Validate</button>
</form>
you can use this script (make sure it is located in the View, in order to use the Url.Action attribute):
<script type="text/javascript">
$("#edit").click(function() {
var form = $("form#myForm");
form.attr("action", "#Url.Action("Edit","MyController")");
form.submit();
});
$("#validate").click(function() {
var form = $("form#myForm");
form.attr("action", "#Url.Action("Validate","MyController")");
form.submit();
});
</script>
If you are working in asp.net with razor, and you want to control multiple submit button event.then this answer will guide you. Lets for example we have two button, one button will redirect us to "PageA.cshtml" and other will redirect us to "PageB.cshtml".
#{
if (IsPost)
{
if(Request["btn"].Equals("button_A"))
{
Response.Redirect("PageA.cshtml");
}
if(Request["btn"].Equals("button_B"))
{
Response.Redirect("PageB.cshtml");
}
}
}
<form method="post">
<input type="submit" value="button_A" name="btn"/>;
<input type="submit" value="button_B" name="btn"/>;
</form>
Here is a good eplanation:
ASP.NET MVC – Multiple buttons in the same form
In 2 words:
you may analize value of submitted button in yout action
or
make separate actions with your version of ActionMethodSelectorAttribute (which I personaly prefer and suggest).
With HTML5 you can use button[formaction]:
<form action="Edit">
<button type="submit">Submit</button> <!-- Will post to default action "Edit" -->
<button type="submit" formaction="Validate">Validate</button> <!-- Will override default action and post to "Validate -->
</form>
<input type="submit" value="Create" name="button"/>
<input type="submit" value="Reset" name="button" />
write the following code in Controler.
[HttpPost]
public ActionResult Login(string button)
{
switch (button)
{
case "Create":
return RedirectToAction("Deshboard", "Home");
break;
case "Reset":
return RedirectToAction("Login", "Home");
break;
}
return View();
}
We can have this in 2 ways,
Either have 2 form submissions within the same View and having 2 Action methods at the controller but you will need to have the required fields to be submitted with the form to be placed within
ex is given here with code Multiple forms in view asp.net mvc with multiple submit buttons
Or
Have 2 or multiple submit buttons say btnSubmit1 and btnSubmit2 and check on the Action method which button was clicked using the code
if (Request.Form["btnSubmit1"] != null)
{
//
}
if (Request.Form["btnSubmit2"] != null)
{
//
}

Resources