Send string from View to Controller using httpGet - MVC - c#

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)
});

Related

Controller action method not being called making a post request in ASP.NET Core

I am trying to use model binding to send a file selected by the user to the controller, this action method is not being hit and I am not sure why. I put a breakpoint inside but it will not get hit.
Here is my import view:
#model FileModel
<h1 class="title-underline">Import file</h1>
<div class="form-group">
<form asp-controller="Import" asp-action="FileImport" method="POST" enctype="multipart/form-data">
<label for="importFile">Select a past grant to import</label>
<input type="file" id="importFile" name="importFile" asp-for="ImportFile">
</form>
<button type="submit" id="btnSubmit" class="btn btn-tnl btn-block">Import</button>
</div>
Here is my model:
public class FileModel
{
public IFormFile ImportFile { set; get; }
}
Here is my action method inside my ImportController:
[HttpPost, ValidateAntiForgeryToken]
public IActionResult FileImport(FileModel model)
{
IFormFile file = model.ImportFile;
var fileName = Path.GetFileName(file.FileName);
var contentType = file.ContentType;
return View("Index");
}
I have provided the controller, action, method, and enctype so I'm not sure what else is missing which is stopping the method from being hit. Is it something to do with the model in the parameter?
One problem that I see is the submit button is outside of the form. It is not doing anything when you click it. Try bringing it into the <form>...</form> block and make the input type = "submit", not "button". Or write a click handler for it that would call submit on the form.
You can check the syntax here
https://www.w3schools.com/html/html_form_elements.asp
<div class="form-group">
<form asp-controller="Import" asp-action="FileImport" method="POST" enctype="multipart/form-data">
<label for="importFile">Select a past grant to import</label>
<input type="file" id="importFile" name="importFile" asp-for="ImportFile">
<input type="submit" id="btnSubmit" class="btn btn-tnl btn-block" value="Import">
</form>
</div>
Your button should be inside form tag. Not outside.
<form>
<button type="submit">Import</button>
</form>

How to manage multiple submit button in my case in MVC 5?

I am a beginner to MVC, I am using MVC 5
_Layout.cshtml code
_Layout.cshtml has navbar, it contains Logout, More button if user already loggedin, Also, it will render body part(Index.cshtml)
//Navbar
#if (ViewBag.name != null)
{
<input type="submit" class="dropdown-item" formaction="Logout" value="Logout" id="btnLogout" />
}
else{
<a class="nav-link" href="#">Login & Signup</a>
}
<input type="submit" class="dropdown-item" formaction="More" value="More" id="btnMore" />
//body
<div class="container body-content">
#RenderBody() //Index.cshtml
</div>
Index.cshtml
Index.cshtml it has some links and also some buttons and anchor links, and it will call partial view (_Login)
#using TestProject.Models
#model ViewSignInAndSignUp
//some html code
<input type="submit" class="dropdown-item" formaction="Action1" value="Action1" id="btnAction1" />
<input type="submit" class="dropdown-item" formaction="Action2" value="Action1" id="btnAction2" />
#Html.Partial("_Login") //partialview
_Login.cshtml
_Login.cshtml this one partial view, if user visit any links, this partial view will popup to request the user to make login. This partial view buttons are working
#model TestProject.Models.SignIn
#using (Html.BeginForm("ControllerSignIn", "Home"))
{
#Html.TextBoxFor(si => si.userName, new { #class = "form-control", #id = "txtLogin" })
#Html.TextBoxFor(si => si.password, new { #class = "form-control", #id = "txtPassword", #type = "password" })
<input type="submit" class="btn btn-sm btn-primary btn-rounded" value="Login" id="btnLoginSubmit" />
}
HomeController
[HttpPost]
public ActionResult Logout(string submitButton)
{
// some coding
return RedirectToAction("Index", "Home");
}
[HttpPost]
public ActionResult More(string str1)
{
// some coding
return RedirectToAction("Index", "Home");
}
[HttpPost]
public ActionResult Action1(string str1)
{
// some coding
return RedirectToAction("Index", "Home");
}
[HttpPost]
public ActionResult Action2(string str1)
{
// some coding
return RedirectToAction("Index", "Home");
}
Now, How can I manage all the buttons from _Layout.cshtml, Index.cshtml, _Login.cshtml(Partial view)
Note
my login button is working, but, logout, more, action1, action2 buttons are not working
Replace this
<input type="submit" class="dropdown-item" formaction="Logout" value="Logout" id="btnLogout" />
with this
Logout
Replace the href with the logout endpoint for your application if different than stated above. Remove any form pointing you to the logout endpoint also as it is not needed anymore.
The submit button submits the form using action URL defined in <form> tag, if you want to use multiple submit buttons then you need to wrap them inside multiple forms with different values of action attribute.
However, there's no need to use multiple submit buttons for those action methods, because redundant <form> tags are inefficient. You may just use #Html.ActionLink() helper to call them like this (and then use styling for those links to look like a button):
#Html.ActionLink("Logout", "Logout", "Home", null, new { #class = "dropdown-item", #id = "btnLogout" })
If the action contains parameter(s), you should add routeValues like example below:
#Html.ActionLink("Action1", "Action1", "Home", new { str1 = "SomeValue" }, new { #class = "dropdown-item", #id = "btnAction1" })
And change HTTP method to GET because ActionLink helper generates anchor <a> tag with href attribute which should use GET method:
[HttpGet]
public ActionResult Logout()
{
// some coding
return RedirectToAction("Index", "Home");
}
The same treatment should be applied to More, Action1 and Action2 action methods as well.
Further reference:
ActionLink helper

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.

Passing textbox value to ActionResult TempData in MVC5

I am very new to MVC , and trying to learn from videos given for MVC. In one of the video i have gone through the use of Tempdata. In the video they have shown created action result with HTTPPOST and pass data from textbox to controller and then to view using Tempdata . I have tried to practice the same . But i am not getting value from textbox,always returning as null. Below is my code,
Controller as below,
public ActionResult Create()
{
return View();
}
[HttpPost]
public ActionResult Create(string name)
{
TempData["uname"] =name;
return RedirectToAction("GetUser");
}
public ActionResult GetUser()
{
return View();
}
View for Create as below,
#{
ViewBag.Title = "Create";
}
<h2>Create New User</h2>
#using (Html.BeginForm())
{
<div>
<p>Enter your name : <input type="text" id="id" placeholder="Enter username"/></p>
<p><input type="submit" id="btnSubmit" value="Create"/></p>
</div>
}
View for GetUser,
#{
ViewBag.Title = "GetUser";
}
<h2>GetUser</h2>
<div>
<h3>Welcome #TempData["uname"].ToString()</h3>
</div>
When i enter value in textbox and press button id parameter in Create action is null. Also i have not created any model class, as in video they have just shown as above code. Please give me some suggestions.
Regards
Sangeetha
if you are not using any model to send the data across , you should provide your textbox with a name attribute and that name attribute must match on the controller action , change your create view text box as shown
#using (Html.BeginForm())
{
<div>
<p>Enter your name : <input type="text" name="name" id="id" placeholder="Enter username"/></p>
<p><input type="submit" id="btnSubmit" value="Create"/></p>
</div>
}
I have added the name attribute to the text box
When you are passing values from view to controller by using input type=submit then you must set name attribute to the input elements,then you need to mention that name in method argument.
<input type="text" name="txtname" id="txtname" placeholder="Enter username"/>
<input type="submit" id="btnSubmit" value="Create"/>
Note : It will only work with input type="submit", it won't work with input type="button"
you don't need bind the Tempdata value with .ToString(). you can directly bind with #TempData["uname"]

Rendering partial view inside a view using AJAX

I'm trying to refresh a partial view inside of a view when a form is submitted. However, whenever I try it just renders the partial view as a normal view. Can someone tell me what I'm doing wrong?
Controller:
public ActionResult ChangeHeatName(string heatName, string updatedHeat)
{
string user = User.Identity.Name;
HomeModel H = new HomeModel();
H.ChangeHeatName(heatName, updatedHeat, user);
ChemViewModel mySlagViewModel = new ChemViewModel();
mySlagViewModel = H.QueryResults(heatName);
return PartialView("PartialChemAnalysis", mySlagViewModel);
}
Partial view form (contained in partial view, not main view):
#using (Ajax.BeginForm("ChangeHeatName", "Home", new AjaxOptions(){UpdateTargetId = "chemDiv" InsertionMode = InsertionMode.Replace}))
{
<section>
Heat Name:<input type="text" name="heatName" value="#Html.ValueFor(x => x.heatname)" style ="width:100px"/>
Change to:<input type="text" name="updatedHeat" value="" style="width: 100px" />
<input type="submit" name="ChangeHeatName" value="Change" />
</section>
}
Index view where partial view is being rendered:
#if(ViewBag.SearchKey == null)
{
<div class="content-wrapper">
<hgroup class="title">
<h1>#HttpContext.Current.User.Identity.Name</h1>
<h2>#ViewBag.Message</h2>
</hgroup>
</div>
}
#using (Html.BeginForm("Index", "Home", "POST"))
{
<div class="searchField">
<input type="text" class="search-query" name="heatSearch" placeholder="Search">
<button class="btn btn-success" type="submit">Search</button>
<br />
#if (ViewBag.AverageSuccessful == true)
{
<input type="text" name="AvgConfirmation" class="search-query" value="Average Submitted Successfully" width:"400px" placeholder="Search" />
}
</div>
}
#if(ViewBag.SearchKey != null)
{
<div>
<div id ="chemDiv">
#Html.Action("PartialChemAnalysis", "Home", (string)ViewBag.SearchKey)
</div>
<div id ="slafDiv">
#Html.Action("PartialSlagView", "Home", (string)ViewBag.SearchKey)
</div>
</div>
}
Index controller that passes SearchKey:
[HttpPost]
public ActionResult Index(string heatSearch)
{
ViewBag.SearchKey = heatSearch;
return View();
}
Currently your ajax.beginform is in your partial view, that's all fine and dandy, but your partialview is not rendered inside your index, so really your never doing the ajax replace logic you're just calling a the action method and getting a full page refresh of the partial view.
here's what would work.
#if(ViewBag.SearchKey != null)
{
<div>
<div id ="chemDiv">
#Html.Partial("ChangeHeatName")
</div>
<div id ="slafDiv">
#Html.Action("PartialSlagView", "Home", (string)ViewBag.SearchKey)
</div>
</div>
}
Now your Ajax.Beginform is rendered in the index view, and when the button is clicked it will refresh.
Edit: you'll need to do something with #Html.Action("PartialChemAnalysis", "Home", (string)ViewBag.SearchKey) possibly stick it in your partial view, because everything in "chemDiv" will now be replaced upon update.
You're not specifying POST in Ajax.BeginForm(). Try this:
#using (Ajax.BeginForm("ChangeHeatName", "Home", FormMethod.Post,
new AjaxOptions(){UpdateTargetId = "chemDiv" InsertionMode = InsertionMode.Replace}))
{...}
Also, stick a breakpoint on your controller action and step through it, see if it's actually hitting return PartialView() or skipping over it.
Posting this because it's not an intuitive fix. Apparently there are issues with MVC 4 and jQuery 1.9.1 so to get this to work I had to change my reference to jQuery 1.7.1

Categories