Bind value to model in Asp.Net MVC Application Part 2 - c#

This is sort of a follow up to Bind value to model in Asp.Net MVC Application.
I have a Model with different control classes. The relevant code:
public class FileUploadModel
{
public HttpPostedFileBase File { get; set; }
}
I have a partial view with the following relevant code:
#Html.TextBoxFor(x => x.File, new { type = "file", id = "File", name = "File" })
Then there is a main view in which the partial view is rendered with the following relevant code:
#using (Ajax.BeginForm("ActionMethods", "Index", new AjaxOptions { UpdateTargetId = "parameterList" }, new { enctype = "multipart/form-data" }))
{
<div id="parameterList">
<div id="verifyBtnDiv" style="display:none;">
**THIS IS WHERE THE PARTIAL VIEW AS SHOWN ABOVE WOULD BE RENDERED**
<input type="submit" id="verifyBtn" value="Verify"/>
</div>
</div>
}
Now when the submit happens, the file does not binds to the model property. The control passes to the controller but i debug and see that its null. ANy suggestions regarding this?

There are a few issues with the code you posted that will prevent what you are attempting to do from working.
First, I am pretty certain that you cannot use the #Html.TextBoxFor helper and convert it to a file input. If it works now, I would not rely on it as you are overriding what it is meant to put out and might break in the future. Let's just put out a file input with an Id and Name matching your ViewModel property.
<input type="file" name="File" Id="File/>
Next, you cannot use Ajax.BeginForm() to upload files. It is a limitation of AJAX, not an issue with the Ajax.BeginForm. So, we will need to update your form element to a normal, Html.BeginForm, with the proper enctype (this is important)
#using (Html.BeginForm("Upload", "MyControllerName", FormMethod.Post, new { enctype = "multipart/form-data"}))
{
<div id="parameterList">
<div id="verifyBtnDiv" style="display:none;">
<!-- Chose to just put the one line here instead of calling a partial-->
<input type="file" name="File" Id="File/>
<input type="submit" id="verifyBtn" value="Verify"/>
</div>
</div>
}
Lastly, if you have to/required to upload the file via AJAX, there are plenty of good recommendations on libraries to use for Ajax file uploads. I personally like the jQuery.Form plugin as it is pretty transparent in the way it handles file uploads.

Related

#Html.EditorFor asp.net core doesn't work for file

I try to make #Html.EditorFor(model => model.file) to put file on web page (file is IFormFile type) in my ASP.NET Core application. But file is null, when i click submit,for some reason, and exception arises.For string everything is OK. Here is HTML code:
#using (Html.BeginForm("tt", "Home", FormMethod.Post))
{
<div class="row">
<div class="col-md-4">
#Html.EditorFor(model => model.file)
</div>
<div class="col-md-8">
<button type="submit" id="btnUpload" class="btn btn-primary">Upload</button>
</div>
</div>
<br />
<div>#Html.DisplayFor(model => model.content)</div>
}
controller code:
public ActionResult tt(Models.FileInfo f)
{
var r = f.content1 + f.file.FileName;
f.content = r;
return View("Demo_index", f);
}
and model:
public class FileInfo
{
public IFormFile file { get; set; }
public string content { get; set; }
public string content1 { get; set; }
}
Is it possible to make #Html.EditorFor(model => model.file) work? Or is there some similar way to make form with file uploading?
The issue is that you're posting as x-www-form-urlencoded, which doesn't support file uploads. You need to use multipart/form-data, instead, which can be achieved via adding the enctype attribute to your form tag:
<form ... enctype="multipart/form-data">
This is possible using Html.BeginForm, but you have to use an overload that requires you to specify a ton of parameters, and it's more pain than it's worth. Besides, in Core, using the tag helpers is much better anyways. Literally all you need is:
<form asp-action="tt" asp-controller="Home" method="post" enctype="multipart/form-data">
...
</form>
If you're doing a postback, i.e. to the same page you're already on, you can remove the asp-action and asp-controller attributes entirely. This will be processed by the built-in FormTagHelper and the right action and such will be generated for you.
FWIW, the same applies with your input as well. Instead of EditorFor, you can simply do:
<input asp-for="file" />
The InputTagHelper will fill in everything else.

How do I return a partial view from my controller to display on my main view?

I have the view:
<div>
<form method="post"action='#Url.Action("ImportProviders")'>
#(Html.Kendo().Upload()
.Name("files")
.HtmlAttributes(new { aria_label = "files" })
.Validation(validation => validation.AllowedExtensions(new string[] { ".csv" }))
)
<p class ="text"> This File Browser only Accepts .CSV File.</p>
<input type="hidden" id="clientNumber" name="Clientid" value="" />
<p class="submit-btn">
<input type="submit" value="Upload Providers" onclick="submit" id="UploadClick" class="k-button k-primary" />
<i class="fa fa-spinner fa-pulse fa-3x fa-fw" id="makeMeDisappear"></i>
<span class="sr-only">Loading...</span>
</p>
</form>
</div>
<br />
<div>
#Html.Partial("ImportedProviderView");
</div>
I have the c# Controller:
public PartialViewResult ImportProviders(String ClientId, IEnumerable<HttpPostedFileBase> files) {
...
ImportProvidersView(result,FaultyRowsTable,"FAULTY ROW");
ImportProvidersView(result, InsertedRows, "INSERTED ROW");
ImportProvidersView(result, UpdatedRowsTable, "UPDATED ROW");
return PartialView("ImportedProviderView", result.OrderByDescending(x=>x.Createdon));
}
But everytime I run this page it takes me to the partial view only, it doesn't inject it into the main view above.
MAIN QUESTION
How do I make it display inside the main view above?
The #Html.Partial method is only going to render the partial view. If you need to execute the controller action that returns the view you will need to use the #Html.Action method
<div>
#Html.Action("ImportProviders", "ControllerName", new { ClientId = <>, files = <> })
</div>
#Html.Partial renders the partial view on the server as part of the main view, which is returned to the browser. If you need something dynamic when the user does something in the browser then you'll probably want to GET/POST to a controller action rendering a new view - or you'll want to call a controller action rendering a partial view using ajax.

Send string from View to Controller using httpGet - MVC

I am new to MVC so please bear with me.
I am trying to send a string from a textbox to a controller method so I can find an object in a database. However, I do not know how to send the string successfully from the view to the controller in a HttpGet request (only in HttpPost)
The code in my view
<div>
<label>Email</label>
#Html.TextBox("email")
</div>
<div class="btn btn-success">
#Html.ActionLink("Edit RSVP", "Edit")
</div>
The ViewResult method in my controller
// Problem is the email parameter is always null
[HttpGet]
public ViewResult Edit(string email)
{
// If the email the typed is find, it will display their contents on to a RsvpForm view
return View("RsvpForm", guestRepository.Find(email));
}
Anyone know how I can send this string through, I would be grateful.
Thanks
Like this:
#using (Html.BeginForm("Edit", "ControllerName", FormMethod.Get))
{
<div>
<label>Email</label>
#Html.TextBox("email")
</div>
<div class="btn btn-success">
<input type="submit" value="Edit RSVP" />
</div>
}
Note: I can't tell from your description whether or not you are trying to do this without reloading the page. This option will post the page to the controller, so you will get a page reload.
If you want this to load without posting the page, you can look into Ajax.BeginForm. Here is a StackOverflow article with a decent primer on the AJAX form.
update
For your example, you may could do something like this if you want to use AJAX. This is all untested, but may be close to what you would need.
First you can create a partial view that represents the user data that you want to display:
RsvpForm.cshtml
#model GuestData
<div class="hdr">Name</div>
<div class="value">#Model.Name</div>
<div class="hdr">Email</div>
<div class="value">#Model.Email</div>
Then you want to make sure that your controller returns the partial view based on the email that is sent via the GET:
GuestDataController.cs
[HttpGet]
public ActionResult Edit(string email)
{
// If the email the typed is find, it will display their contents on to a RsvpForm view
return PartialView("RsvpForm", guestRepository.Find(email));
}
Then you create the AJAX form to submit the request via a GET and load the partial view without reloading the page: view.cshtml
<script src="#Url.Content("~/Scripts/jquery.unobtrusive-ajax.js")" type="text/javascript"></script>
#using (Ajax.BeginForm("Edit", "GuestData", null, new AjaxOptions { UpdateTargetId = "UserData", HttpMethod = "Get" }, null))
{
<div>
<label>Email</label>
#Html.TextBox("email")
</div>
<div class="btn btn-success">
<input type="submit" value="Edit RSVP" />
</div>
}
<div id="UserData"></div>
The easiest way to do it is to create a form as follow :
#using(Html.BeginForm("Edit", ControllerName, FormMethod.GET))
{
#Html.Label("Email")
#Html.TextBox("email")
<input type="submit" value="Edit RSVP"/>
}
or you can use Jquery to change the link when textbox value change (which I do not recommend):
$('input[name=email]').on('change' function()
{
var value = $(this).val();
var href = $('.btn').next('a').attr('href');
href += '?email='+value;
$('.btn').next('a').attr('href', href)
});

Trouble with #Html.BeginForm in ASP.NET MVC

I have a form that looks like this:
#using (Html.BeginForm("Login", "Home", FormMethod.Post, new { #class = "nav-login-form" }))
{
#Html.TextBoxFor(m => m.LoginForm.Username, new {#placeholder = "username"})
#Html.HiddenFor(m => m.LoginForm.Username)
#Html.PasswordFor(m => m.LoginForm.Password, new { #placeholder = "password" })
#Html.HiddenFor(m => m.LoginForm.Password)
<input type="submit" value="login"/>
}
However, when this form is submitted the controller method does not seem to be executed. It has a signature that looks like this:
[HttpPost]
public ActionResult Login(NavBarLogin loginForm)
My form is in a partial view with HomepageViewModel as the model type. This model has a LoginForm object inside of it, which is what the form is supposed to post to the controller. The model is passed into the partial view from the Index view like this:
#Html.Partial("_NavBarPartial", Model)
My best guess as to why this form is not working correctly is because the model defined in the view is not the same as the model object the form is using. However, I can't simply use NavBarLogin as the model type since other parts of the model are used elsewhere in the partial. I could attempt to split things up further, but is that really a requirement to make this form work? Am I even correct in my assumptions?
Edit:
My forum is being rendered like this, is action supposed to be blank?
<form action="" class="nav-login-form" method="post">
<input id="LoginForm_Username" name="LoginForm.Username" placeholder="username" type="text" value="" />
<input id="LoginForm_Password" name="LoginForm.Password" placeholder="password" type="password" />
<input type="submit" value="login"/>
You can use the the Prefix property of BindAttribute
[HttpPost]
public ActionResult Login([Bind(Prefix="LoginForm")] NavBarLogin loginForm)
Since you inputs are being rendered like
<input type="text" name="LoginForm.Username" value=.../>
and NavBarLogin has property Username (not a complex property LogInForm with property UserName), what this does is to effectively strip "LoginForm." from the posted values so they will bind correctly

Upload of two different files, from two different inputs

I'm currently trying to handle the upload of two different files from two different <input type="file"/>s.
For example:
#using (Html.BeginForm("AddIssue", "Magazine", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
<fieldset>
<div class="editor-field">
<div class="editor-label">Issue: </div>
<input type="file" name="issueFile" id="issueFile"/>
</div>
<div class="editor-field">
<div class="editor-label">Cover: </div>
<input type="file" name="issueCover" id="issueCover"/>
</div>
<button type="submit">Save</button>
</fieldset>
}
I've figured out how to receive a file (or files) from one input, but can't find any appropriate information on how to receive files from multiple inputs.
I already have a method for POST, but can't figure out what shall I receive on post.
[HttpPost, Authorize]
public ActionResult AddIssue(string dummy)
{ }
After the comment, here is a more specific solution...
You need to ensure that your Controller Action parameters are named the same as the name attribute on your form fields. This should work for you:
public ActionResult AddIssue(HttpPostedFileBase issueFile, HttpPostedFileBase issueCover)
{ }
Remember, it is the name attributes that are used to identify the fields from the controller. The id attributes mean nothing, and do not have to match.

Categories