File upload in C# with ASP.NET MVC without razor - c#

I am trying to submit a form containing a file upload using c# ASP MVC with Entity. My problem is that the file is always null.
The view :
#model Com.Work.With.Me.Models.ObjVM
<!DOCTYPE html>
<html>
<head>
<title>Test</title>
</head>
<body>
<form id="formObj" action="AddMe">
<input type="file" id="objPdfFile" name="Obj.PdfFile" />
</select>
<input type="text" id="objName" name="Obj.Name" />
</form>
The viewmodel :
public class ObjVM
{
public string Name{ get; set; }
public HttpPostedFileBase PdfFile{ get; set; }
public ObjVM()
{
}
}
The controller :
public ActionResult AddMe(ObjVM obj)
{
//her obj.Name is fine
//but obj.PdfFile is null
return View();
}
Any ideas?

Thanks to #DiskJunky, I corrected my form adding method="post" enctype="multipart/form-data":
<form id="formObj" action="AddMe" method="post" enctype="multipart/form-data">
<input type="file" id="objPdfFile" name="Obj.PdfFile" />
</select>
<input type="text" id="objName" name="Obj.Name" />
</form>
And my controller adding [HttpPost] :
[HttpPost]
public ActionResult AddMe(ObjVM obj)
{
//obj.PdfFile is not null anymore !
return View();
}

Add Your Ui to this Code `enctype = "multipart/form-data"` Code
#using (Html.BeginForm("Action Name", "Control Name", null, FormMethod.Post, new { enctype = "multipart/form-data" }))
{
<input type="file" id="objPdfFile" value="#Model.PdfFile" name="Obj.PdfFile" />
</select>
<input type="text" id="objName" value="#Model.Name" name="Obj.Name" />
}

Related

How do i pass two text inputs into ActionResult method

I've been working on a large project for a few days. Its all finished except for this part. I'm trying to pass 2 text boxes into my home controller method.
I've tried to use "model." and "item." but with no luck. it always passes null
<p>
#Html.ActionLink("Display", "Home", FormMethod.Post)
</p>
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div>
Month:<input type="text" name="Month" id="MonthInput">
Extra:<input type="text" name="Extra" id="ExtraInput"><br /><br />
<input type="submit" value="Add" class="btn btn-default"> <br> <br>
</div>
}
and in the home controller is
[HttpPost]
public ActionResult Display(String Month, String Extra)
{
if (ModelState.IsValid)
{
...
return RedirectToAction("Index");
}
return view;
}
I want it to pass whatever value is typed in the textboxes when the "Add" Button is clicked but it gives null
try this,
In View
#using (Html.BeginForm("Display", "Home", FormMethod.Post))
{
#Html.AntiForgeryToken()
<div>
Month:<input type="text" name="Month" id="MonthInput">
Extra:<input type="text" name="Extra" id="ExtraInput"><br /><br />
<input type="submit" value="Add" class="btn btn-default"> <br> <br>
</div>
}
In Controller,
[HttpPost]
public ActionResult Display(SomeClass someClass)
{
if (ModelState.IsValid)
{
...
return RedirectToAction("Index");
}
return view;
}
Create Normal class name SomeClass, name as per your requirment,
public class SomeClass{
public string Month {get;set;}
public string Extra {get;set;}
}
the name attribute of inputs should match to properties of SomeClass, it will map automatically, you then can access the value by using someClass object
someClass.Month and someClass.Extra
In order to correctly map to the action's parameters, you must use the name attribute.
#using (Html.BeginForm("Display", "Home"))
{
#Html.AntiForgeryToken()
<div>
Month:<input type="text" name="Month" id="MonthInput">
Extra:<input type="text" name="Extra" id="ExtraInput"><br /><br />
<input type="submit" value="Add" class="btn btn-default">
</div>
}
Totally unrelated, but it seems you have 2 nested forms and one of them POSTs to a php page. Is that desired?
Also, remove the following code because it does not make any sense:
<p>
#Html.ActionLink("Display", "Home", FormMethod.Post)
</p>
To add on to the previous answer, I would suggest accepting the form as a FormCollection in the controller, because the form does not seem to be tied to the model:
[HttpPost]
public ActionResult Display(FormCollection collection)
{
if (ModelState.IsValid)
{
string month = collection["Month"];
string extra = collection["Extra"];
return RedirectToAction("Index");
}
return View();
}
namespace Your.Models
{
public class DisplayModel
{
public string Month {get;set;}
public string Extra {get;set;}
}
}
[HttpPost]
public ActionResult Display(DisplayModel model)
{
if (ModelState.IsValid)
{
string month = model.Month;
string extra = model.Extra;
return RedirectToAction("Index");
}
return View();
}
#using Your.Models
#model DisplayModel
#using (Html.BeginForm("Display", "Home", new { id="displayview" }))
{
#Html.AntiForgeryToken()
<div>
Month:<input type="text" name="Month" id="MonthInput">
Extra:<input type="text" name="Extra" id="ExtraInput"><br /><br />
<input type="submit" value="Add" class="btn btn-default">
</div>
}

Passing view model from razor view to controller action

I have a problem, when using asp.net core 2.2.
I have a model named "Test".
public class Test
{
public string Email { get; set; }
}
And a controller named "UserController"with these actions:
public IActionResult Test()
{
var test = new Test
{
Email = "Hamid#gmail.com"
};
return View(test);
}
[HttpPost]
public IActionResult Test(Test param)
{
if (ModelState.IsValid)
{
}
return View();
}
and view with named "test.cshtml" is:
#model Test
#{
Layout = null;
}
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>Test</title>
</head>
<body>
<form asp-controller="User" asp-action="Test" asp-area="Account" method="post">
<div class="form-group row">
<div class="col-lg-3 col-12">
<label asp-for="Email" class="col-form-label">Email:</label>
</div>
<div class="col-lg-9 col-12">
<input asp-for="Email" class="form-control email"
value="#Model.Email" autofocus="autofocus" />
</div>
</div>
<input type="submit" value="Send" />
</form>
</body>
</html>
When i sending model to the view, no problem,
But when I click on submit button for sending form to the action,then my model is null.
My problem solved.
With remove this line:
#removeTagHelper Microsoft.AspNetCore.Mvc.TagHelpers.InputTagHelper, Microsoft.AspNetCore.Mvc.TagHelpers

Html.Hidden() generating blank values in HTML

I have a form on my view:
#using (Html.BeginForm("ClearData", "MemberPass", FormMethod.Post))
{
<div>
#foreach (var property in ViewData.ModelMetadata.Properties)
{
#Html.Hidden(property.PropertyName, property.Model)
}
</div>
<button>Clear</button>
}
and the following action methods:
public ActionResult Index()
{
MemberPassInfoViewModel memberPassInfoViewModel = new ServiceUtilities().GetEventDetails(DateTime.Now.Date);
return View("Index", memberPassInfoViewModel);
}
public ActionResult GetMemberPassInfo(MemberPassInfoViewModel currentMemberPassInfoValues)
{
MemberPassInfoViewModel updatedMemberPassInfoViewModel = new ServiceUtilities().GetMemberPassInfoViewModel(currentMemberPassInfoValues);
return View("Index", updatedMemberPassInfoViewModel);
}
public ActionResult ClearData(MemberPassInfoViewModel currentMemberPassInfoValues)
{
MemberPassInfoViewModel updatedMemberPassInfoViewModel = new ServiceUtilities().ClearData(currentMemberPassInfoValues);
return View("Index", currentMemberPassInfoValues);
}
In debug I can see that the model's two properties are present. However when I view the generated HTML, one of the properties has a blank value:
<input id="SearchCode" name="SearchCode" type="hidden" value="23" />
<input id="FullName" name="FullName" type="hidden" value="" />
I noticed that this could be fixed by replacing:
#Html.Hidden(property.PropertyName, property.Model)
with:
<input type="hidden" value="#property.Model" name="#property.PropertyName" />
Which generates:
<input type="hidden" value="23" name="SearchCode" />
<input type="hidden" value="Alex Robert" name="FullName" />
Why does the #Html.Hidden() method not work, but explicitly writing the <input> tag does work?

On Post action method the List<className> and SelectList properties of a ViewModel are always null [duplicate]

I have a really wierd issue with MVC.
My models keeps getting submitted empty.
And it's probably really simple, but I just can't find the issue.
My model looks like this:
public class LoginModel
{
public string Username;
public string Password;
}
My controller like this:
[HttpGet]
public ActionResult Login()
{
return View();
}
[HttpPost]
public ActionResult Login(LoginModel loginTest)
{
if (loginTest.Username != "x" && loginTest.Password != "y")
{
ModelState.AddModelError("a", "Login failed.");
return View(loginTest);
}
else
{
return RedirectToAction("Home", "Welcome");
}
}
And the view is also very simple, like this.
#model LoginSolution.Models.LoginModel
#{
Layout = null;
}
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>Login</title>
</head>
<body>
#using (Html.BeginForm("Login", "Home"))
{
<div> <span>Username : </span>
#Html.EditorFor(model => model.Username)
<br />
<span>Password : </span>
#Html.EditorFor(model => model.Password)
<br />
#Html.ValidationSummary()
<br />
<input type="submit" value="Login" name="Login" />
</div>
}
</body>
</html>
This is not a question about security or best practice.
This is just a question regarding why the model keeps returning itself as empty upon submitting.
Your model contains fields, not properties (no getter/setter) so the model binder cannot set the values. Change your model to
public class LoginModel
{
public string Username { get; set; }
public string Password { get; set; }
}

Post form from modal partial view to a different controller with a routeprefix attribute

I have a partial view that has a form - I launch this partial from the Home controller.
#using (Html.BeginForm("CloudContent","Files", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
<div id="container"></div>
<input type="submit" name="PostMe" title="Submit" value="Submit Form" />
#Html.HiddenFor(m => m.MyProperty);
#Html.HiddenFor(m => m.SelectedIds);
}
I want to post this form to the Files controller, however the files controller has a route prefix:
[RoutePrefix("sth/api/v1/files")]
Which results in my form action being empty.
It doesn't seem to be added to named routes, so I cannot use the beginrouteform. Also, I have little influence over the application, so it's best handled in my form or partial view...
The method that I want to post to in the files controller:
[HttpPost]
[Route("getcloudcontent")]
public List<ConnectedFile> CloudContent(CloudFilesModel model)
{
//do magic
}
UPDATE:
Here is another example which includes partial view / child action:
HomeController.cs:
using System.Web.Mvc;
public class HomeController : Controller
{
[Route("~/")]
public ActionResult Index()
{
return View();
}
[Route("ModalContent")]
[ChildActionOnly]
public ActionResult ModalContent()
{
return View();
}
}
FilesController.cs:
using System.Web.Mvc;
[RoutePrefix("sth/api/v1/files")]
public class FilesController : Controller
{
[HttpPost]
[Route("getcloudcontent")]
public ActionResult CloudContent(string model)
{
return Content("test");
}
}
Views\Home\Index.cshtml:
<!DOCTYPE html>
<html>
<head>
<title>Test</title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
</head>
<body>
<button type="button" class="btn btn-primary btn-lg" data-toggle="modal" data-target="#myModal">
Show modal
</button>
<div class="modal fade" id="myModal" tabindex="-1">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-body">
#Html.Action("ModalContent")
</div>
</div>
</div>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
</body>
</html>
Views\Home\ModalContent.cshtml:
#using (Html.BeginForm("CloudContent", "Files", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
<div id="container"></div>
<input type="submit" name="PostMe" title="Submit" value="Submit Form" />
}
Global.asax.cs:
using System.Web.Mvc;
using System.Web.Routing;
public class MvcApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
RouteTable.Routes.MapMvcAttributeRoutes();
}
}
And the result HTML:
<!DOCTYPE html>
<html>
<head>
<title>Test</title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
</head>
<body>
<button type="button" class="btn btn-primary btn-lg" data-toggle="modal" data-target="#myModal">
Show modal
</button>
<div class="modal fade" id="myModal" tabindex="-1">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-body">
<form action="/sth/api/v1/files/getcloudcontent" enctype="multipart/form-data" method="post">
<div id="container"></div>
<input type="submit" name="PostMe" title="Submit" value="Submit Form" />
</form>
</div>
</div>
</div>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
</body>
</html>
There is something different that is wrong with your code. I ran your code and it worked without any issues.
Here is the code:
FilesController.cs:
using System.Web.Mvc;
namespace Controllers
{
[RoutePrefix("sth/api/v1/files")]
public class FilesController : Controller
{
[Route("")]
public ActionResult Index()
{
return View();
}
[HttpPost]
[Route("getcloudcontent")]
public ActionResult CloudContent(string model)
{
return Content("test");
}
}
}
Index.cshtml:
#using (Html.BeginForm("CloudContent", "Files", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
<div id="container"></div>
<input type="submit" name="PostMe" title="Submit" value="Submit Form" />
}
Global.asax.cs:
using System.Web.Mvc;
using System.Web.Routing;
public class MvcApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
RouteTable.Routes.MapMvcAttributeRoutes();
}
}
When I go to http://localhost/sth/api/v1/files I see the following HTML:
<!DOCTYPE html>
<html>
<head><title>Test</title></head>
<body>
<form action="/sth/api/v1/files/getcloudcontent" enctype="multipart/form-data" method="post"> <div id="container"></div>
<input type="submit" name="PostMe" title="Submit" value="Submit Form" />
</form>
</body>
</html>
Notice that form action has the correct URL which includes prefix.

Categories

Resources