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.
Related
I've completed testing my ASP.NET Core app locally, and it works fine. However I'm getting 404 errors for a trigger on my view after publishing to our UAT server and I cannot determine why. I'm possibly missing something obvious and would appreciate fresh eyes. Thank you.
I have tried amending the routing in StartUp and attempted mixed routing in my controller.
Relevant part of Configure method in startup.cs:
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=StartPage}/{id?}");
});
Relevant form in my StartPage view:
<form action="#Url.Action("StartSlsProcess", "Home")" method="post" enctype="multipart/form-data" id="trigger">
<div id="process-trigger">
#(Html.DevExtreme().Button()
.Text("Start SLS")
.Type(ButtonType.Success)
.UseSubmitBehavior(true)
)
</div>
</form>
Method in HomeController:
[HttpPost]
public ActionResult StartSlsProcess()
{
var empty = new string[0];
ConsoleApp.Program.StartProcessFromUI(empty);
return new EmptyResult();
}
I would expect when the button is pushed on the view that it triggers the StartProcessFromUI method on my console app, continues the separate process and refreshes the view, as it does locally.
Edit: what is further confusing the issue is that my other Action works fine, and is set up the same:
<form action="#Url.Action("Upload", "Home")" method="post" enctype="multipart/form-data" id="uploader">
<div id="fileuploader-container">
#(Html.DevExtreme().FileUploader().Name("file")
.ID("file-uploader")
.Accept("*")
.UploadMode(FileUploadMode.Instantly)
.UploadUrl(Url.Action("Upload", "Home"))
//.OnUploadError("fileUploader_onUploadError")
//.OnValueChanged("fileUploader_valueChanged")
)
</div>
</form>
HomeController method:
[HttpPost]
public ActionResult Upload()
{
try
{
var file = Request.Form.Files["file"];
var path = Path.Combine(_hostingEnvironment.WebRootPath, "uploads");
if (!Directory.Exists(path))
Directory.CreateDirectory(path);
using(var fileStream = System.IO.File.Create(Path.Combine(path, file.FileName))) {
file.CopyTo(fileStream);
fileStream.Flush();
}
MoveFileFromServer(path, file);
}
catch (Exception e)
{
Console.WriteLine(e);
throw;
}
return new EmptyResult();
}
Additionally, the method on my ConsoleApp, StartProcessFromUI actually gets hit, it's just that the 404 Error is then returned in the foreground.
At least for the C# side, I can tell you it is not a programming issue. As a general rule the networking code does not care if the other end is on the same computer, the same switch, or the Voyager 2 Probe.
Making certain there is a path there is a Networking Problem, not a programming one. As your Title says, the error is a 404/Routing one. So it is definitely somewhere in the Networking. Maybe the Server is not set up to allow external (non-Localhost) Connections, or some similar security feature. Many default profiles are created with such settings for security reasons. It could also be a overagressive Firewall.
When in doubt, you can just verify it with a simple HTML file, that should be delivered as stored on the disk.
I'm using ASP.Net Core 2 Razorpages with dropzonejs to have a dragndrop fileupload on my index site after the user drops a file I want to redirect to my LoadingPage.
However I'm having problems with the page being redirected. Strangely the OnGet() method of the page I want to redirect to is being called, but the site in the browser never gets updated. Other redirects work just fine, so I suspect the issue to be something with dropzonejs.
Well, here is my code:
index.cshtml
<div id="fileuploadcontainer">
<form method="post"
class="dropzone"
id="music-dropzone"
asp-page="./Index">
</form>
<br />
</div>
index.cshtml.cs
public async Task<IActionResult> OnPostAsync(IFormFile file)
{
if (!ModelState.IsValid)
{
return Page();
}
[...]//this here is my file uploading, but the problem still persits even when removed
return RedirectToPage("/LoadingPage/Loading");
}
Loading.cshtml.cs
public async Task<IActionResult> OnGet()
{
[...]//this part here gets called just fine, but the site doesnt redirect, even when it is minfied to only return Page() :(
return Page();
}
I also already tried to remove the async modifiers, but to no avail...
Edit - Workaround:
I have tried any possible combination and solution I can think of but my problem still persists. However I found a nice workaround, you can use the events of dropzonejs and then redirect the page using JS. The code for that would be:
<script>
Dropzone.options.[yourDropzoneElementId] = {
maxFilesize: 10, // Mb
init: function () {
// Set up any event handlers
this.on('success', function () {
window.location.replace("/LoadingPage/Loading");
});
}
};
</script>
I appreciate any help, thank you!
Am I missing something or asp.net core allows to post script tag in user text fields? In Previous versions of asp.net mvc I needed to allow it by [AllowHtml] attribute.
Is there a way how enable validation agains potentially dangerous values?
I'm free to submit value like
<script src='http://test.com/hack.js'></script>
during form post.
Model:
using System.ComponentModel.DataAnnotations;
namespace Test.Models
{
public class TestModel
{
[MaxLength(500)]
public string Content { get; set; }
}
}
Controller:
using Microsoft.AspNetCore.Mvc;
using Test.Models;
namespace Test.Controllers
{
public class HomeController : Controller
{
public IActionResult Index()
{
var model = new TestModel { Content = "Test" };
return View();
}
[HttpPost]
public IActionResult Index(TestModel model)
{
if(!ModelState.IsValid)
return View(model);
return Content("Success");
}
}
}
View:
#model TestModel
<form asp-action="Index" asp-controller="Home" method="post">
<div asp-validation-summary="All"></div>
<label asp-for="Content">Content<strong>*</strong></label>
<span asp-validation-for="Content"></span>
<input asp-for="Content" type="text" />
</div>
</form>
ASP.NET Core does not have a feature similar to Request validation, as Microsoft decided, that it’s not a good idea.
For more information see the discussion on the ASP.NET Core issue 'Default middleware for request validation, like IIS has'.
That means that validation has to take place on the inbound model. And that in the Razor (.cshtml)
you should output user provided input like #Model.Content, which encodes the given string.
Please bear in mind that those escaping techniques might not work when the text that was output is not inside a Html part.
So don't use #Html.Raw(..) unless you know that the data provided has been sanitized.
Supplement:
You might want to consider a Web Application Firewall (WAF)
for a generic protection against malicious requests (e.g. XSS or SQL Injection).
For protecting your users against an XSS attack you might also have a look at
providing a Content Security Policy (CSP).
I've been following this guide for the HandleError attribute:
blogs.msdn.com
which I use like this (AccountController):
[HandleError(View="ErasErrorPage")]
public ActionResult Index()
{
ViewBag.admins = _accountMapper.GetAdmins(false);
ViewBag.members = _accountMapper.GetMembers(false);
ViewBag.Countries = _countryMapper.GetCountries();
return View();
}
This code throws an exception because _accountMapper.GetAdmins(false) fails because of a System.Data.EntityException.
I've put the ErasErrorPage view in my Shared folder and I've added <customErrors mode="On"/> but the ErasErrorPage does not show up. All I get when the error occurs is a yellow screen of death saying:
Obviously, setting the mode to "Off" or "RemoteOnly" doesn't solve the problem.
Anyone has an idea why this doesn't work?
EDIT
If I surf directly to http://localhost:3527/Account/Index, I do get the correct ErasErrorPage, but I don't want that. I want the website to automaticly redirect to that page when an exception is thrown somewhere. Is this possible?
EDIT2
I've put the [HandleError(View="ErasErrorPage")] attribute right before every single Public ActionResult methodName() { ... } method, and I still get the Yellow Screen of Death saying I need to change the mode to "Off" or "RemoteOnly"...
Make sure that the ErasErrorPage view doesn't itself throw an exception. Here are the steps I did and which worked fine for me:
Create a new ASP.NET MVC 3 Project using the default Visual Studio wizard
Add ~/Views/Shared/ErasErrorPage.cshtml with the following content:
#{
Layout = null;
}
<!DOCTYPE html>
<html>
<head>
<title>ErasErrorPage</title>
</head>
<body>
<div>
OOPS
</div>
</body>
</html>
Modify HomeContoller to look like this:
public class HomeController : Controller
{
[HandleError(View = "ErasErrorPage")]
public ActionResult Index()
{
throw new Exception("oops");
}
}
In web.config put:
<customErrors mode="On" />
Navigate to /Home/Index => the custom error page is displayed as expected
Since this doesn't work at all, I've found a very good alternative:
Custom error pages on asp.net MVC3
I also found out why it failed:
We were trying to connect to the database before we tried rendering views. The HandleError attribute won't even be triggered by that (I think). The method above does do that. It handles any exception, anywhere.
It does work, I have a BaseController with the attribute [HandleError(View = "Error")] and an Error view in Shared with a dynamic model (should be HandleErrorInfo) and at the Index action in the HomeController I am throwing an exception:
throw new Exception("Test exception");
The error view is then rendered and displays the correct information.
ErrorView:
<div class="errorMessage">
<h1 class="errorHeader">#Model.Exception.GetType().Name</h1>
<cite class="errorAction">thrown in #Model.ControllerName #Model.ActionName</cite>
<p class="errorMessage">thrown in #Model.Message</p>
</div>
you experts probably knowing the easyiest ways to open/find a file from asp.net mvc application.
could you tell me please how to do that, if i want for example to find and upload a photo from my PC.
Thanks and take care,
Ragims
This article may help you.
The article will show how to upload a
file from client to server location in
ASP.Net MVC application in 5 easy
steps.
Two samples:
example one
example two with unit testing
Just a simple HTML file input in your view will suffice:
<input type="file" name="MyFile" id="MyFile" />
Then accept the file in your controller action:
public ActionResult Upload(HttpPostedFileBase myFile)
{
// save or process file here...
return View();
}
Also, remember to set <form enctype="multipart/form-data"> in your form.