Set form post timeout - c#

I have a form that upload a file and the server has to process a large operation that takes several minutes.
My code:
.cshtml:
#using (Html.BeginForm("MyAction", "MyController", FormMethod.Post,
new { enctype = "multipart/form-data" }))
{
<input type="file" name="file"/>
<input type="submit" value="submit" />
}
Controller:
[HttpPost]
public ActionResult MyAction(HttpPostedFileBase file)
{
// Process a large operation here.
return View();
}
I know it's possible to do it with web.config configuration and with server code.
My question: Is it possible to do with client side configuration?
I ask that because when using XMLHttpRequest like jQuery.ajax its possible to set the timeout, so is it possible to do in html form tag or something?

One of the options is to create AsyncController and then you can set [AsyncTimeout(xxxx)] or [NoAsyncTimeout] attributes in your action.
Here is an example on how to do it

Related

BeginForm messes up controller path value in .NET 6

after migrating my app from .NET Framework 4.8 to .NET6, Html.BeginForm has started to change the slash into "%2F" in the controller path, which causes problems because then they become unreachable.
Basically, this:
<form action="/Admin/Report/DownloadReport" enctype="multipart/form-data" method="post">
Becomes this:
<form action="/Admin%2FReport/DownloadReport" enctype="multipart/form-data" method="post">
Example of code where it happens:
<div class="form-container">
#using (Html.BeginForm("DownloadReport", "Admin/Report", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
#Html.Hidden("requestReportName", "PageReport");
<span class="epi-cmsButton">
<input class="epi-cmsButton-text epi-cmsButton-tools epi-cmsButton-Export" type="submit" name="btnSubmitDownloadPageReport" id="btnSubmitDownloadPageReport" value="Download Report" />
</span>}
</div>
What can be the cause of that strange behavior? I have not found any information that Html.Beginform has became obsolete in .NET6.
Edit:
My route mapping:
endpoints.MapControllerRoute(
name: "Admin",
pattern: "Admin/{controller}/{action=Index}");
ASP.NET MVC
If you are working with the Built-In Controller Factory using controller name in format Admin/Report actually does not correct. When the built-in controller factory looking for a controller it uses controller name and looking for Your_Controller_NameController class in YourApp.Controllers.* namespaces.
It is possible to map the specific URL route by defining different namespaces using the namespaces parameter of the MapRoute() method in the ASP.NET MVC.
Try to fix the controller name in the #using (Html.BeginForm("DownloadReport", "Admin/Report", FormMethod.Post, new { enctype = "multipart/form-data" })) to Report. I suppose your application will find the DownloadReport action method without a problem.
See RouteCollectionExtensions.MapRoute Method
ASP.NET Core
I suppose after fixed the controller name in the Html.BeginForm("DownloadReport", "Admin/Report"...) to "Report" your application migration will work correct.
If you will have routing problems provide more information or see the following post: Restrict route to controller namespace in ASP.NET Core

Razor view not sending input to controller?

I am using a razor file for my view with this post form:
#using (Html.BeginForm("Save", "MyEventController", FormMethod.Post))
{
<md-input-container class="md-block" flex-gt-xs="">
<label>Title</label>
<input type="text" name="title" />
</md-input-container>
<md-input-container class="md-block">
<label>Address</label>
<input type="text" name="address" id="txtAddress">
</md-input-container>
<md-button class="md-raised">
<input type="submit" value="Save" />
</md-button>
}
I want to send my input to my controller in Controllers/EventController.cs as show below:
public class MyEventController : Controller
{
[HttpPost]
public void Save(FormCollection collection)
{
InputEvent y = new InputEvent();
y.title = collection["title"];
y.address = collection["address"];
}
}
The Save() methods seems to never be called. how do i submit to Save()?
I am developing in Visual Studio 2015
Remove the text "Controller" when you specify the controller. Change it to,
Html.BeginForm("Save", "MyEvent", FormMethod.Post)
Remove the word "Controller" from your second parameter "MyEventController". So it should be "MyEvent".
Furthermore, I would create a Model (M from MVC) and when the form is posted, instead of receiving FormCollection, it will receive a nice model instead. ASP MVC will take care of binding for you.
Also, as others have pointed out, you may want to eventually return something back to the client to specify if the form submission and processing was successful. Therefore, your action should not return void. Most of the time in cases such as this, you should use the PRG pattern-it is very important to use this pattern.
Try ActionResult instead of void.
From MSDN:
Writes an opening tag to the response. When the user submits the form, the request will be processed by an action method.

Data in view different thank backend

To put simply, I am scanning a drivers license with a magnetic strip card reader, using javascript RegEx to get the data I need, sending that data to the server as JSON via an ajax call, and then sending back a partial view with an Ajax.BeginForm with the data filled out.
In fact, all of this is working great. The problem is that I'm trying to alter the data on the server in C# before sending it to the view, but no matter what I do the original non-formatted data is showing up on the page still. I even stepped through the entire process, and looking at the Model data for the view shows that it received the correct data. Yet when the view is displayed, the non-formatted data (which does not actually exist in the Model object when I browse it) is what shows up in the text boxes.
function LoadVisitorCreatePartial(CardData) {
$.post(webroot + "Visitor/GetVisitorLogCreateVisitorForm", CardData, function (data) {
$('#visitor-info').append(data);
});
}
Above is the relevant javascript I am using for the call. I am using Carl Raymond's jquery card swipe to pull the data and I implemented some of my own RegEx to get the data I need for "CardData", which is JSON.
[HttpPost]
public ActionResult GetVisitorLogCreateVisitorForm(DriversLicenseForm CardData)
{
var form = visitorService.GetForm(CardData);
return PartialView("Form", form);
}
Above is the controller function that is being called. DriversLicenseForm is essentially the JSON object, as a C# class.
public VisitorForm GetForm(DriversLicenseForm CardData)
{
var textInfo = CultureInfo.InvariantCulture.TextInfo;
var DateOfBirth = DriversLicense.ParseDriversLicenseDate(CardData.DateOfBirthString);
CardData.FirstName = ConvertToTitleCase("i'm ron burgundy?");
CardData.LastName = textInfo.ToTitleCase(CardData.LastName);
var form = new VisitorForm();
if (DateOfBirth != null)
{
CardData.DateOfBirth = Convert.ToDateTime(DateOfBirth);
}
form = Mapper.Map<VisitorForm>(CardData);
form.ID = -1;
form = SetFormProperties(form);
return form;
}
In the above code you can see that I was getting annoyed. I decided to manually set the name and despite me setting CardData.FirstName to something completely different (verified when stepping through in debug mode) when the form comes back, it just shows my name from drivers license. I also have two title case functions because initially I thought that was the problem and found a non-textinfo solution, though that changed nothing and after debug stepping through, the data in CardData is being changed and updated properly. I feel it is worth noting one more time that the data is changed in debug mode in CardData and in the form after AutoMapper maps it out, my code appears to be working fine, except the actual view displays the original data despite there being no reference or reason for it to even know that data exists.
I literally have no idea what to do at this point.
EDIT: Here is the view code
#using (Ajax.BeginForm("PostForm", "Visitor", new AjaxOptions { HttpMethod = "POST", UpdateTargetId = "visitor-info", OnSuccess = "VisitorPostback" }))
{
#Html.AntiForgeryToken()
#Html.ValidationSummary(true)
#Html.HiddenFor(model => model.ID)
<div class="editor-label">
#Html.LabelFor(model => model.LastName)
</div>
<div class="editor-field">
#Html.TextBoxFor(model => model.LastName, new { #class = "focus" })
#Html.ValidationMessageFor(model => model.LastName)
</div>
<p>
<input type="submit" class="btn btn-primary" value="Save" />
</p>
}
I cut out a lot of the actual textboxes, but left one as an example. They are all done the same way.
When sending data to a MVC Post action method, the ModelState gets populated with the data that you send. This is for instances when a form is POSTed that has validation errors, you can simply return the view back and all of the users form inputs are shown as well along with the validation errors.
Typically after a POST, you would redirect (PRG -> Post Redirect Get) to another action method, but it doesn't look like you would be able to do that here easily.
It looks like those ModelState values are being held onto the return of the "Form" view and is binding those to the matching form elements. Try adding ModelState.Clear() to your POST action method to see if that is what is causing the issue.
[HttpPost]
public ActionResult GetVisitorLogCreateVisitorForm(DriversLicenseForm CardData)
{
ModelState.Clear();
var form = visitorService.GetForm(CardData);
return PartialView("Form", form);
}

Ajax.BeginForm absolute url MVC CORS

Is there any way to get the Ajax.BeginForm to output a absolute url rather than just a relative one?
I am trying to get some forms working with CORS on a site hosted on another server.
At the moment I am parsing the form with jquery onsuccess in the ajax options.
I am not any pointers to a tutorial on writing an extension for it would be handy
Is there any way to get the Ajax.BeginForm to output a absolute url
rather than just a relative one?
Yes, but you need to specify the Url in the AjaxOptions and not use the overload which takes action and controller names:
#using (Ajax.BeginForm(new AjaxOptions { Url = Url.Action("Foo", "Bar", null, "http") }))
{
...
}
Url.Action has an overload where you could specify the protocol to be used which generates absolute urls. And if you wanted to use the same protocol as the one used to request the current action instead of hardcoding it you could use the following:
#using (Ajax.BeginForm(new AjaxOptions { Url = Url.Action("Foo", "Bar", null, Request.Url.Scheme) }))
{
...
}
Here:
#using (Ajax.BeginForm(new AjaxOptions {
Url = "http://www.domain.com/whatever" ,
Confirm = "...",
// and other options...
}))
{
// html controls or helpers here...
}

Razor Virtual Path issue

The controller is:
public class HomeController : Controller
{
public ActionResult LogOn()
{
return View();
}
[HttpPost]
public ActionResult LogOn(string captcha)
{
if (captcha == HttpContext.Session["captcha"].ToString())
return Content("ok");
else
return Content("failed");
}
public CaptchaImageResult ShowCaptchaImage()
{
return new CaptchaImageResult();
}
}
The view is:
<%using (Html.BeginForm())
{ %>
<p><img src="/Home/ShowCaptchaImage" /></p>
<p>Please enter the string as shown above:</p>
<p><%= Html.TextBox("captcha")%></p>
<p><input type="submit" value="Submit" /></p>
<% } %>
Everything goes well, the captcha image is rendered (CaptchaImageResult writes a jpg in the response stream). But if i use the razor view engine there is no captcha image rendered.
How to fix it?
And one more thing: is it a good way to display captcha?
Later edit: <img src=#Href("../../Home/ShowCaptchaImage") /> works fine.
The problem wasn't because razor it was because in the first example i was using Visual Studio Development server and in the second one i was using IIS
<img src="/Home/ShowCaptchaImage" />
This causes the browser to request /Home/ShowCaptchaImage from the root of the HTTP origin (scheme+domain+port) on which you host the application. You need to map the URL to reflect things like any virtual folders in which the app is hosted. If I'm not wrong and this is the problem you are facing, take a look at ResolveUrl/ResolveClientUrl equivalents for Asp.Net Razor? (I haven't tested it, but it looks good).
Also, you could diagnose the problem easily using Firebug or an equivalent tool in another browser - take a look at the requests which are made and you will see what the browser actually requests.

Categories