I created a simple form that works fine when I run it in Visual Studio, but fails on my website with a 404 error.
I have an Action set up to receive only "post" messages using [HttpPost].
If I change the Acton to receive "get" messages, the Action is called, but the form information is not passed along.
This site is written with .Net MVC, could there be some kind of security or something on the server that may need to be changed to allow for "post" calls?
Controller Code -
[HttpGet]
public ActionResult Tester1()
{
return View("Tester1");
}
[HttpPost]
public ActionResult Tester2(MyModel myModel)
{
return View("Tester2", myModel);
}
Tester1.cshtml Code -
#model FS.Models.MyModel
#using (Html.BeginForm("Tester2", "Comics", FormMethod.Post))
{
<div>
Enter Text -
#Html.TextBoxFor(m => m.property1)
</div>
<div>
<input type="submit" value="SEND!" />
</div>
}
Tester2.cshtml Code -
#model FS.Models.MyModel
You entered - #Model.property1
Global.asax.cs Code -
routes.MapRoute(
"Tester2Route", // Route name
"{controller}/Tester2", // URL with parameters
new { controller = "Comics", action = "Tester2" } // Parameter defaults
);
(the code above is just a summarized version, you can visit the actual site here - http://funkysmell.com/Comics/Tester1/)
I was able to get this to work.
The problem is that the server you are running on is wanting a trailing slash (/) after the URL. So when I looked at your example, the URL generated is
<form action="/Comics/Tester2" method="post">
If you add a trailing slash it will work. i.e.
<form action="/Comics/Tester2/" method="post">
Take a look here to get more information.
Why is ASP.NET MVC ignoring my trailing slash?
There are links in that answer to a few blogs which should help you out.
Related
I am uploading a file using via a view linked to a controller however after the upload is uploaded the application is either trying to refresh or redirect and I need to prevent this. May you please point me in the right direction to avoid redirection and refresh? I have done a bit of reading and I suspect that this line action="/api/BulkUpload">might be causing the problem.
My Controller
using System;
using System.Diagnostics;
using System.IO;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;
using System.Web;
using System.Web.Http;
using Repositories.BulkUpload;
using Repositories.Interfaces.BulkUpload;
namespace SimSentinel.Controllers
{
//[Authorize]
public class BulkUploadController : ApiController
{
private readonly IBulkUploadRepository _bulkUploadRepository;
public async Task<HttpResponseMessage> PostFile()
{
// Check if the request contains multipart/form-data.
if (!Request.Content.IsMimeMultipartContent())
{
throw new HttpResponseException(HttpStatusCode.UnsupportedMediaType);
}
string root = HttpContext.Current.Server.MapPath("~/Files");
var provider = new FormDataStreamer(root);
try
{
StringBuilder sb = new StringBuilder(); // Holds the response body
// Read the form data and return an async task.
await Request.Content.ReadAsMultipartAsync(provider);
// This illustrates how to get the form data.
foreach (var key in provider.FormData.AllKeys)
{
foreach (var val in provider.FormData.GetValues(key))
{
sb.Append(string.Format("{0}: {1}\n", key, val));
}
}
// This illustrates how to get the file names for uploaded files.
foreach (var file in provider.FileData)
{
FileInfo fileInfo = new FileInfo(file.LocalFileName);
sb.Append(string.Format("Uploaded file: {0} ({1} bytes)\n", fileInfo.Name, fileInfo.Length));
}
return new HttpResponseMessage()
{
Content = new StringContent(sb.ToString())
};
}
catch (System.Exception e)
{
return Request.CreateErrorResponse(HttpStatusCode.InternalServerError, e);
}
}
public class FormDataStreamer : MultipartFormDataStreamProvider
{
public FormDataStreamer(string rootPath) : base(rootPath) { }
public FormDataStreamer(string rootPath, int bufferSize) : base(rootPath, bufferSize) { }
public override string GetLocalFileName(HttpContentHeaders headers)
{
var srcFileName = headers.ContentDisposition.FileName.Replace("\"", "");
return Guid.NewGuid() + Path.GetExtension(srcFileName);
}
}
}
}
MY HTML
<form name="form1" method="post" enctype="multipart/form-data" action="/api/BulkUpload">
<div>
<label for="caption">Image Caption</label>
<input name="caption" type="text" />
</div>
<div>
<label for="image1">Image File</label>
<input name="image1" type="file" />
</div>
<div>
<input type="submit" value="ok" />
</div>
</form>
You're correct. When you submit the form, the file is sent to the controller via a HTTP POST request and the page is either, necessarily, refreshed or redirected. If you don't want to the page to refresh or redirect, then you'll have to use AJAX to post the file to the controller.
From a Mozilla Developer document on HTTP requests,
The GET method requests a representation of the specified resource.
Requests using GET should only retrieve data.
The POST method is used to submit an entity to the specified
resource, often causing a change in state or side effects on the
server.
From these notes on Web Programming from Nanyang Technological University,
[The] POST request method is used to "post" additional data up to the server
(e.g., submitting HTML form data or uploading a file). Issuing an HTTP
URL from the browser always triggers a GET request. To trigger a POST
request, you can use an HTML form with attribute method="post" or
write your own network program. For submitting HTML form data, POST
request is the same as the GET request except that the URL-encoded
query string is sent in the request body, rather than appended behind
the request-URI.
So, you can see that since you're posting a file to the server using a standard HTTP request, it is necessarily going to refresh or redirect in some way.
To avoid this, you can use jQuery to asynchronously post the file to the server without refreshing the page. There are plenty of articles on how to do this. I suggest you give it a try and post another question if you get stuck.
Upload file using jQuery and post it to Controller
ASP Snippets - Upload file using jQuery AJAX in ASP.Net MVC
C# Corner - File Upload Through JQuery AJAX In ASP.NET MVC
Thanks so much for the help it guided me in the right direction. I eventually got my answer from this [How to submit html form without redirection? . The Iframe approach is the simplest approach it is a temporary fix seeing as some articles are saying that although it is still supported by most modern browsers it has been deprecated.
I am fetching data from a table and displaying it. Every row in the webpage will have a edit hyperlink. That pops up a edit window for respective row. The contents of the pop up are replaced by the #Html.Partial() function. now the form gets submitted from the Partial view. The Interesting fact is first time I edit any row it works fine. However the second time I am getting the following error:
Server Error in '/' Application.
The resource cannot be found.
Description: HTTP 404. The resource you are looking for (or one of its dependencies) could have been removed, had its name changed, or is temporarily unavailable. Please review the following URL and make sure that it is spelled correctly.
Requested URL: /Edit
Version Information: Microsoft .NET Framework Version:4.0.30319; ASP.NET Version:4.7.2623.0
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit([Bind(Include = "SerialNumber,ProjectName,Nature,Phase,StartDate,EndDate,ProjectLead,LeadAlias,Onsite,OffShore,ProjectDetail,EditedBy,CreatedBy")] ProjectModel projectModel)
{
projectModel.EditTime = DateTime.Now;
if (ModelState.IsValid)
{
db.Entry(projectModel).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
return View(projectModel);
}
The form gets submitted using the following button:
<input type="submit" value="Save" class="btn btn-default" formaction="Edit" formmethod="post" />
Please let me know if anything else do you need. Thanks in advance.
#shyju 's answer really helped I changed the formaction and it worked
I'm a bit new to MVC and have no idea why following issue happening.
According to tutorial we can handle form posts by this code:
View:
<form action = "/learning/Goto" method="GET">
<input type="text"name="gotoUrl"/>
<input type="submit" name="Goto"/>
</form>
where Learning is Controller and goto is method as I understood.
Controller:
public ActionResult Goto(string gotoUrl)
{
return Redirect(gotoUrl);
}
I have a question: all I did according to the tutorial video and it worked in the video. However I have some trouble.
In my view I have warning:
"Path E:\Programming\MVC_Learning\learning not found" in the following line:
<form action = "/learning/Goto" method="GET">
I think that need to setup path to Controller folder. But what I don't understand the most the fact that it works and really redirect to input address but only in this form: "http:// mysite.net". If I write mysite.net I get exception
HTTP Error 404.0 - Not Found
Requested URL
http://localhost:64074/learning/mysite.net
Physical Path E:\Programming\C_SHARP\MVC_Learning\MVC_Learning\learning\mysite.net
So could somebody explain me following:
1. Why it works with http but does not work without?
2. Why I get warning on
<form action = "/learning/Goto" method="GET">
?
Your controller action url wrong, Instead of "/learning/Goto" use(Most Preferred way in MVC)
<form action = "#Url.Action("Goto","learning")" method="GET">
or just remove "/" and
<form action = "learning/Goto" method="GET">
I am trying to understand the AngularJS routing when it is used with ASP.net MVC. I am following this article to understand AngularJS routing. My query is specific to the usage of 'templateURL'. I understand that in pure AngularJS routing, templateUrl points to a specific '.html' page. But in the many example applications that I have seen in the internet for AngularJS and ASP.net MVC, I have seen that templateURL does not point to a specific .html, but a path of the view folder is given, not the .html file (or .cshtml file, which i know can be processed only by ASP.net MVC framework). For example from the article, following is the routing information given in the AngularJS javascript:
NbCapp.config(function ($routeProvider) {
$routeProvider
.when('/ondemand', {
controller: 'onDemandController',
templateUrl: 'ondemand/ondemand'
})
.when('/results', {
controller: 'resultsController',
templateUrl: 'results/results'
})
.otherwise({ redirectTo: '/results' });
});
As observed from the above, all the routing, points to a folder not a .html file. Could anyone please help me understand how this works.
I understand that in pure AngularJS routing, templateUrl points to a specific '.html' page.
Not necessarily. It doesn't matter what extension is or whether there is extension at all or not. The only thing that matters is Content-Type of the document fetched as template. So as long as it's text/html - it can be used as template. (Actually GET request for template will be issued and response processed as template (will be displayed on the page), so it doesn't even matter what server responds with Angular will just take responseText of the response data, but better if it is text/html).
In your example, templateUrl: 'results/results' might point to some dynamic framework resolved user-friendly path without any extensions, which responds with HTML content.
AngularJS does not necessarily have to point to an HTML page. What you have specified above is a combination of controller/action. When you call an action you get a processed CSHTML, VBHTML, or ASPX as an HTML response.
For example, specifying:
templateUrl: 'Account/LogOn'
will instantiate an AccountController and call LogOn action that will return PartialViewResult.
templateUrl does not require only .html template. Basically ui-route loads the content from given template url and accept that Content-Type : 'text/html'. Template loadin g is done by ajax.
So you are free to load any template with any extension but with valid path.
In Asp.net MVC we define custom routing in RouteConfig File. Suppose in RouteConfig we have declared custom route as follows:
routes.MapRoute("AngularTemplates", "almight/{name}", new { controller = "Home", action = "Template" });
and in app.js file, we have configured angular route as follow:-
var app = angular.module("BeautyParlorAppModule", ["ngRoute"]);
app.config(function ($routeProvider) {
debugger
$routeProvider
.when("/DetailView",
{
templateUrl: "almight/detailsView",
controller: "DetailviewController"
}
)
.when("/ListView",
{
templateUrl: "almight/_ListView",
controller: "ListViewController"
}
);
});
In HTML file we have action like:
<div class="row">
<div class="col-md-12">
<div class="nav">
<ul>
<li>Show ListView</li>
<li>Show DetailView</li>
</ul>
</div>
</div>
Upon clicking on link will locate home controller of MVC and call action Template with Name parameters _ListView or detailsView
public class HomeController : Controller
{
public ActionResult Index(string id)
{
return View();
}
public ActionResult Template(string name)
{
if (name == null || !Regex.IsMatch(name, #"^[-\w]+$"))
throw new ArgumentException("Illegal template name", name");
relativeViewPath=String.Format("~/Views/Home/{0}.cshtml",name);
return View(relativeViewPath);
}
public ActionResult About()
{
ViewBag.Message = "Your application description page.";
return View();
}
public ActionResult Contact()
{
ViewBag.Message = "Your contact page.";
return View();
}
}
I just started playing with MVC and I've run into a roadblock. I'm using a partial view as a User Login flyout on the header of each page using OpenID. When the user clicks on the provider (similar to stackoverflow) it authenticates and then either returns to the calling page or redirects to the signup page. The code works flawlessly under Firefox and Chrome but bombs out in IE. The "provider" parameter in the controller is always sent as null. Is there some sort of bug involving posting input names/values in IE or am I doing something wrong?
This is what my openid partial view looks like:
<% using (Html.BeginForm("Authenticate", "Membership", new { ReturnUrl = Request.Url }, FormMethod.Post))
{
if (!Page.User.Identity.IsAuthenticated)
{ %>
<div class="openidProviders">
Log in or join using one of these OpenID providers:
<div class="large buttons">
<div class="provider"><div><%= Html.SubmitImage("provider", "/Content/common/images/google.gif", new { value = "Google" })%></div></div>
<div class="provider"><div><%= Html.SubmitImage("provider", "/Content/common/images/Yahoo.gif", new { value = "Yahoo" })%></div></div>
<div class="provider"><div><%= Html.SubmitImage("provider", "/Content/common/images/AOL.gif", new { value = "AOL" })%></div></div>
<div class="provider"><div><%= Html.SubmitImage("provider", "/Content/common/images/OpenId.gif", new { value = "OpenId" })%></div></div>
</div>
</div>
<% }
}
%>
And the controller logic is here:
[AcceptVerbs(HttpVerbs.Post), ValidateInput(false)]
public void Authenticate(string provider, string ReturnUrl)
{
// Figure out provider endpoint
// Authentication function calls here
}
Well, it looks like IE, for once, is the only browser properly following the HTML spec according to this post.
The HTML specification only requires
that x, y coordinates where the image
submit button was clicked be sent to
the web server. IE follows the
specification. The browsers that send
the value="..." parameter are doing
their own thing outside of the HTML
specification.
Basically, I need to use a submit input instead of SubmitImage and then style the background of the button accordingly. Not the optimal solution but at least it works. This is what the final solution looks like. If anyone knows a way of getting the SubmitImage to work properly, let me know.
Replace the buttons above with ones that look like this:
<input type="submit" value="Google" class="google_OpenID" name="provider" />
And the CSS class:
.google_OpenID
{
background-image: url(/Content/common/images/google.gif);
width:75px;
cursor:pointer;
color:transparent;
height:35px;
border:none;
}