I got 2 actions in my controller, I want to choose which action to execute by checkbox in my razor view.
here is my controller:
public ActionResult Person(string searchString)
{
var person = from p in db.Persons
select p;
if (!String.IsNullOrEmpty(searchString))
{
person = person.Where(oo => oo.Name.ToUpper() == searchString);
}
return View(person);
}
public ActionResult Job(string jobString)
{
var jobs = from j in db.Jobs
select j;
if (!String.IsNullOrEmpty(jobString))
{
jobs = jobs.Where(oo => oo.Name.ToUpper() == jobString);
}
return View(jobs);
}
when I check a case I would like to execute the query search for this specific case
here is my view:
<div>
<form method="POST">
<div>
<input type="checkbox" name="Person" value="Person" style="margin-left: 54px"/>Person
</div>
<div class="Job">
<input type="checkbox" name="Job" value="Job" />Job
</div>
#using (Html.BeginForm())
{
<p>
<input type="text" name="SearchString" style="margin-left: 90px;" />
<input type="submit" value="Search" />
</p>
}
</form>
Post to a single action method, then call one of your existing methods depending on the value of the checkbox.
public ActionResult Search(bool isJobSearch, string searchString)
{
if (isJobSearch)
{
return Job(searchString);
}
else
{
return Person(searchString);
}
}
private ActionResult Person(string searchString)
{
// As your example
}
private ActionResult Job(string jobString)
{
// As your example
}
I am just correcting your html
Your html contains two form tags. I am not sure about the usage of form with in form tags. html.beginform will create internally another form tag when gets executed.So better one form tag will contain all elements to make a post.
#using (Html.BeginForm("Search","Home"))
{
<div>
<input type="checkbox" name="Person" value="Person" style="margin-left: 54px"/>Person
</div>
<div class="Job">
<input type="checkbox" name="Job" value="Job" />Job
</div>
<p>
<input type="text" name="SearchString" style="margin-left: 90px;" />
<input type="submit" value="Search" />
</p>
}
}
in controller
public ActionResult Search(FormCollection form)
{
//do some condition based on your needs
if(form["SearchString"]=="Job")
return RedirectToAction("Job");
else
return RedirectToAction("Person");
}
public ActionResult Person()
{
}
public ActionResult Job()
{
}
Related
I have a method that I only use in one property where I upload photos so I only use the Photo property
I don't want to put the object as a parameter but a string that will be a replacement for the object and overwrite the Photo or in another way when using a Dto that fails to do gets null.
It's a function that works for me but I use the whole object as a parameter when I only use the PHOTO URL:
public async Task<string> UploadPhotos(IFormFile file, Product product)
{
string wwwPath = _environment.WebRootPath;
var path = Path.Combine(wwwPath, "images", file.FileName);
if (file.Length > 0)
{
using var stream = new FileStream(path, FileMode.Create);
await file.CopyToAsync(stream);
}
return product.PhotoUrl = file.FileName;
}
What I tried to do:
public async Task<string> UploadPhotos(IFormFile file, string photoUrl)
{
Product product = new()
{
PhotoUrl = photoUrl
};
string wwwPath = _environment.WebRootPath;
var path = Path.Combine(wwwPath, "images", file.FileName);
if (file.Length > 0)
{
using var stream = new FileStream(path, FileMode.Create);
await file.CopyToAsync(stream);
}
return product.PhotoUrl = file.FileName;
}
It doesn't work for me when I try to upload it doesn't show me the picture
Controller:
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> AddProduct([FromForm] ProductViewModel model)
{
ModelState.Clear();
await _photoService.UploadPhotos(model.Photo,model.PhotoUrl);
if (ModelState.IsValid)
{
await _productRepository.AddProduct(model.Product!);
return RedirectToAction(nameof(Index));
}
return View();
}
ViewModel:
public class ProductViewModel
{
public Product Product { get; set; } = null!;
public string PhotoUrl { get; set; } = string.Empty;
public IFormFile Photo { get; set; } = null!;
}
View:
#model Solid_Project.Models.ProductViewModel
#{
ViewBag.Title = "AddProduct";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<article>
<section>
<form asp-action="AddProduct" enctype="multipart/form-data" method="post">
<div asp-validation-summary="ModelOnly"></div>
<div class="form-group">
<label asp-for="#Model.Product!.Name"></label>
<input asp-for="#Model.Product!.Name" class="form-control" placeholder="Enter Name" style="width:30%">
<span asp-validation-for="#Model.Product!.Name" class="validation"></span>
</div>
<br />
<div class="form-group">
<label asp-for="#Model.Product!.Description"></label>
<input asp-for="#Model.Product!.Description" class="form-control" placeholder="Enter Description" style="width:30%">
<span asp-validation-for="#Model.Product!.Description" class="validation"></span>
</div>
<br />
<div class="form-group">
<label asp-for="#Model.Product!.CategoryId"></label>
<div>
<select asp-for="#Model.Product!.CategoryId" asp-items="ViewBag.Category" style="width:30%" class="dropdown-toggle dropdown-toggle-design"
data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"></select>
</div>
<span asp-validation-for="#Model.Product!.CategoryId" class="validation"></span>
</div>
<br />
<div class="form-group">
<label asp-for="#Model.Photo"></label>
<input type="file" asp-for="#Model.Photo" accept="image/*" class="form-control" style="width:30%" />
<span asp-validation-for="#Model.Photo" class="validation"></span>
</div>
<br />
<input type="submit" value="Create" class="btn btn-primary" />
</form>
</section>
</article>
#section Scripts {
#{
await Html.RenderPartialAsync("_ValidationScriptsPartial");
}
}
I am very new to this and I am trying to show multiple entries to show and have a single button for each entry to edit them. I thought it would be really easy but For some reason I am not getting the clicked entity. Is there way of getting modified entity without running javascript?
Any help will be appreciated. I couldn't find any example code that does this. There are many examples that returns all the entries but not the single element.
Here is my entity class Resource:
public class Resource
{
[Required]
public string title { get; set; }
[Required]
public int value { get; set; }
[Key]
[Required]
public int id { get; set; }
}
On the controller side I have:
[HttpGet]
public IActionResult Index()
{
return View(resources);
}
[HttpPost]
public IActionResult Index(Resource resource)
{
return View(resource);
}
Here is the View and EditorTemplates
#model learningMVC.Models.Resource[]
#{
ViewData["Title"] = "index";
}
<h1>index</h1>
<fieldset>
#Html.EditorFor(x => x);
</fieldset>
#addTagHelper "*, Microsoft.AspNetCore.Mvc.TagHelpers"
#model learningMVC.Models.Resource
<div>
First Name:<br />
<form asp-action="Index" asp-controller="Home">
<input asp-for="id" class="form-controller" />
<input asp-for="value" class="form-controller" />
<input asp-for="title" class="form-controller" />
<input type="submit" value="Save" class="btn btn-primary" id="btnSubmit_#Model.id" />
</form>
</div>
In your case, you should use particalview instead of editfor, you can see my demo below.
_ResourcesPartical.cshtml:
#model Resource
<div>
<form method="post" asp-action="Index">
First Name:<br />
<input asp-for="id" class="form-controller" />
<input asp-for="value" class="form-controller" />
<input asp-for="title" class="form-controller" />
<input type="submit" value="save" />
</form>
</div>
Your Index view:
#model List<Resource>
#foreach(var m in Model)
{
#await Html.PartialAsync("_ResourcesPartical", m)
}
Controller:
[HttpGet]
public IActionResult Index()
{
//here you get your data.below is my fake data.
var resources= new List<Resource>
{
new Resource
{
id = 1,
title = "aa",
value = 3
},
new Resource
{
id = 2,
title = "bb",
value = 4
}
};
return View(resources);
}
[HttpPost]
public IActionResult Index(Resource resource)
{
return RedirectToAction("Index");
}
Test result:
Here is the model:
public class UserModel()
{
public string UserName{get;set;}
public string UserPassword{get;set;}
public string UserSource{get;set;}
}
Here is the front-end:
#model Sample.Models.UserModel
#addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
<form asp-controller="Login" asp-action="LoginIn.html" method="post">
<div>
<h3>Name</h3>
<span asp-validation-for="UserName"></span>
</div>
<input asp-for="UserName" placeholder="Your username" />
<div>
<h3>Password</h3>
<span asp-validation-for="UserPassword"></span>
</div>
<input asp-for="UserPassword" placeholder="Your password" type="tel" />
<button type="submit">Login in</button>
</form>
The front-end is a Partial View. It is referenced like this:
#await Html.PartialAsync("/Views/Contact/LoginIn.cshtml", new Sample.Models.UserModel() { UserSource = "From website" })
And here is the controller:
[HttpPost]
[ValidateAntiForgeryToken]
[Route("LoginIn.html")]
public IActionResult LoginIn(Sample.Models.UserModel)
{
if (ModelState.IsValid)
{
}
return Redirect();
}
Well, when the form submitted, the controller only can get the UserName/UserPassword but can't get the UserSource unless I add a
<input asp-for="UserSource" />
into front-end.
I don't want to show the UserSource to the user in the front-end(even hide it by CSS).
How can I solve this problem? Thank you.
You can use ajax to post form,here is a demo:
TestFormAction:
public IActionResult TestForm() {
UserModel u= new UserModel { UserSource = "111" };
return View(u);
}
LoginController:
public IActionResult Index()
{
return View();
}
[HttpPost]
[ValidateAntiForgeryToken]
[Route("Login/LoginIn.html")]
public IActionResult LoginIn(UserModel u)
{
if (ModelState.IsValid)
{
}
return Ok();
}
TestForm.cshtml:
<form id="myForm" method="post">
<div>
<h3>Name</h3>
<span asp-validation-for="UserName"></span>
</div>
<input asp-for="UserName" placeholder="Your username" />
<div>
<h3>Password</h3>
<span asp-validation-for="UserPassword"></span>
</div>
<input asp-for="UserPassword" placeholder="Your password" type="tel" />
<button type="submit">Login in</button>
</form>
#section scripts{
<script>
$('#myForm').submit(function (event) {
event.preventDefault(); // avoid to execute actual form submit.
var model = {};
model.UserName = $("#UserName").val();
model.UserPassword = $("#UserPassword").val();
model.UserSource =#Model.UserSource;
var token = $('input[name="__RequestVerificationToken"]').val();
$.ajax({
url: '#Url.Action("LoginIn.html", "Login")',
type: 'POST',
data: model,
headers: { "RequestVerificationToken": token },
success: function (data) {
window.location.href = "/Login/Index";
}
});
});
</script>
}
result:
I created an ASP.NET Core 3.1 project. I have a form in it with several checkbox lists. I can get the values into the properties in POST and they are correctly filled in (e.g. List SelectedItems). However for some custom fields I have to do a validation in OnPost() method and if the conditions are not met or a ModelState is not valid, it return Page(). Normally I would expect that every property that was filled in in the form is still filled in, but the checkboxes are always empty and not a single one is checked. The other data (radio buttons, textboxes, etc.) are still filled in.
I even tried to put the values within the Razor page, but even then neither of the checkboxes was checked.
Here is an example of one of the checkboxes:
In Razor page:
#for (var i = 1; i <= 10; i++){
<input name="AreChecked" type="checkbox" id="#i" value="#i" /> #i<br />
<input type="hidden" value="true" id="#i" name="AreChecked" />}
Behind code:
[BindProperties]
public class TestFormModel : PageModel
{
[BindProperty]
public List<int> AreChecked { get; set; }}
public IActionResult OnPost()
{
//some other form check statements here
//...
if (ModelState.IsValid)
{
//process data code...
}
return Page();
}
Can someone help me with this?
You could use JQuery to achieve as shown :
#page
#model RazorPages3_1.AddimgModelModel
<div class="row">
<div class="col-md-4">
<form enctype="multipart/form-data" method="post">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="Petimg.PetName" class="control-label"></label>
<input asp-for="Petimg.PetName" class="form-control" />
<span asp-validation-for="Petimg.PetName" class="text-danger"></span>
</div>
<div class="form-group">
<input asp-for="Uploads" class="form-control" />
</div>
#for (var i = 1; i <= 10; i++)
{
<input name="AreChecked" type="checkbox" id="#i" value="#i" /> #i<br />
<input type="hidden" value="true" id="#i" name=""AreChecked" />
}
<div class="form-group">
<input type="submit" value="Create" class="btn btn-primary" />
</div>
</form>
</div>
</div>
<div>
<a asp-page="Index">Back to List</a>
</div>
#section Scripts {
<script>
var checkedlist = #Html.Raw(Json.Serialize(Model.AreChecked));;
if (checkedlist.length > 0) {
$.each(checkedlist, function (index, value) {
$('input[type=checkbox]').each(function () {
var id = $(this).attr("id");
if (id == value) {
$(this).attr('checked', 'checked');
}
})
});
}
</script>
}
Result
i am using .net core with razor pages and i have a model as a list of object as below :
public class Member
{
public List<User> member { get; set; }
}
public class User
{
public String fname { get; set; }
public String lname { get; set; }
}
and i have a form to fill the object as below :
<form asp-controller="Population" asp-action="AddMember" method="post" class="form-horizontal" role="form" style="font-family:Cairo-Bold">
<div class="new-help add-form-container">
<input asp-for="member.LastName" type="text" />
<input asp-for="member.Firstname" type="text" />
</div>
and the user can add a object dynamically from the page when he clicks on a button i duplicate for him for div to add a new member as below :
<div class="row">
<div class="col-lg-12">
<a class="clone-button"><u> Add another</u></a>
</div>
</div>
$(function () {
$(".clone-button").on('click', function () {
var ele = $(this).closest('.new-help').clone(true);
$(this).closest('.new-help').after(ele);
});
});
how can i bind the text fields in the form in order to return to the controller the list of members added on submit?
You should generate element with index number like this code :
$(function () {
$("#add").click(function (e) {
e.preventDefault();
var i = $(".items").length;
var n = '<input type="text" class="items" name="ListItems[' + i + '].Name" />';
$("#item-list").append(n);
});
});
Please see this link for more information:
link
What I find is that List field in model needs to begin with a capital letter.Otherwise, I could not get a correct model binding.
public class Member
{
public int MemberId { get; set; }
public List<User> Users { get; set; }
}
Create view
#model AddMember.Models.Member
<form asp-action="Create" method="post">
<div class="form-group" id="item-list">
Add
<br/>
<input type="text" asp-for="Users" class="items" name="Users[0].fname"/>
<input type="text" asp-for="Users" class="items" name="Users[0].lname" />
</div>
<input type="submit" value="Create" class="btn btn-default" />
</form>
#section Scripts {
<script>
$(function () {
$("#add").click(function (e) {
e.preventDefault();
var i = ($(".items").length) / 2;
var n = '<input type="text" class="items" name="Users[' + i + '].fname" />' +
'<input type="text" class="items" name="Users[' + i + '].lname" />'
$("#item-list").append(n);
});
});
</script>
}
Controller:
[HttpPost]
public async Task<IActionResult> AddMember(Member member)