How send params from tag helper? - c#

I want pass params from view to controller, but dont know how make it with asp.net tag-helpers. What i make wrong? Params not received on controller.
<form asp-controller="Role" asp-action="Create" asp-route-returnurl="#ViewBag.ReturnUrl" method="post" class="form-horizontal" role="form">
<div class="form-group">
<label asp-for="#Model.Name" class="col-md-2 control-label"></label>
<div class="col-md-10">
<input asp-for="#Model.Name" class="form-control" />
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Create" class="btn btn-default" />
</div>
</div>
</form>
How pass data from inputbox to controller?
[HttpPost]
public ActionResult Create(string rolename)
{
try
{
this.context.Roles.Add(new IdentityRole()
{
Name = rolename
});
this.context.SaveChanges();
}

In your action method change rolename to name. The default model binder doesn't know where to initialize this rolename from. Additionally you can inspect what is posted on the server via fiddler.

Related

Data annotation validation happening on page load in ASP.Net Core

I am facing the issue of data validation being executed on load of a new page even though it is clearly coming from a Get method. Is there something that's triggering the validations on page load?
I have a button on a view to add a new Student record in the new screen :
View :
<a type="button" id="btnAddStudent" href='#Url.Action("Details","Student")' class="btn btn-tertiary" title="Add Student">Add Student</a>
The controller code for the Details action method in Student Controller is as follows.
[HttpGet]
public ActionResult Details(StudentInfo model)
{
//This is populating the model parameters as expected.
helper.StudentInfo(ref model);
return View(model);
}
The view for the Details screen is as follows. The page loads but is throwing validation errors even though it's a Get method.
<form id="frmSubmit" asp-action="Details" asp-controller="Student" method="post">
<input type="hidden" asp-for="StudentId" />
<div class="row">
<div class="col-xs-12">
#Html.ValidationSummary("", new { #class = "alert alert-danger validation" })
</div>
</div>
<div class="row">
<div class="col-xs-12">
<div class="form-group">
<label asp-for="Name">*StudentName</label><br />
<input asp-for="Name" class="form-control" maxlength="100" placeholder="Enter student name..." />
<span asp-validation-for="Name" class="text-danger"></span>
</div>
</div>
</div>
<div class="row">
<div class="col-xs-12">
<div class="form-group">
<label asp-for="AddressLine1"></label><br />
<input asp-for="AddressLine1" class="form-control" placeholder="Enter address..." />
<span asp-validation-for="AddressLine1" class="text-danger"></span>
</div>
</div>
</div>
<div class="row">
<div class="col-xs-12">
<div class="form-group">
<label asp-for="AddressLine2"></label><br />
<input asp-for="AddressLine2" class="form-control" maxlength="100" />
<span asp-validation-for="AddressLine2" class="text-danger"></span>
</div>
</div>
</div>
<div class="box">
<div class="form-group pull-right">
<button type="submit" class="btn btn-primary" value="save"> Save</button>
</div>
</div>
Is there something I am doing wrong? I have verified that the debug control goes to the Get method.There's alos no on load scripts which are doing any sort of validation.
1.Your get method contains the model parameter, when the request hit the method it will judge the ModelState by default. And when you hit the get method by your shared <a>, it send request without any data, so the ModelState is invalid.
2.Default Tag helper displays ModelState's value not Model.
In conclusion, you will render the ModelState error although it is a get method.
Two ways you can resolve this problem. The first way is that you can add ModelState.Clear() before you return View:
public ActionResult Details(StudentInfo model)
{
ModelState.Clear(); //add this....
helper.StudentInfo(ref model);
return View(model);
}
The second way is do not add the model as parameter:
public ActionResult Details()
{
var model = new StudentInfo();
helper.StudentInfo(ref model);
return View(model);
}

HttpPost Model ID is always 0

I have an Update page getting a ViewModel containing my Model. When I load it to the page everything works fine but when I submit the changes my Model's ID is ALWAYS 0, I mean LITTERALY ALWAYS. I am following a tutorial, I did exactly what he did and STILL 0.
This is my POST method where I'm passing the VM in parameter.
[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult Update(ExpenseVM obj)
{
if (ModelState.IsValid)
{
_db.Expenses.Update(obj.Expense);
_db.SaveChanges();
return RedirectToAction("Index");
}
return View(obj);
}
And here is my HTML/C# code for the ID
<input type="hidden" asp-for="Expense.Id" value="#Model.Expense.Id" name="Id"/>
When I load my page my ID is loaded and everything works fine.
During debugging this is what I have in my HTML :
<input type="hidden" value="1" name="Id" data-val="true" data-val-required="The Id field is required." id="Expense_Id">
I found out why it didn't work.
My HTML was like this
<form method="post" asp-action="Update">
<div class="border p-3">
<div class="form-group row">
<h2 class="text-black-50 pl-3">Update Expense</h2>
</div>
<div class="row">
<input type="hidden" asp-for="Expense.Id" value="#Model.Expense.Id" name="Id"/>
<div class="col-12">
... BLABLABLA
</div>
</div>
</div>
</form>
So I just moved the input line from inside <div class="row> to <form method="post" asp-action"Update"> and removed all these useless tags like name="Id" value="#Model.Expense.Id" type="hidden"
And now it looks just like this
<form method="post" asp-action="Update">
<input asp-for="Expense.Id" hidden/>
<div class="border p-3">
<div class="form-group row">
<h2 class="text-black-50 pl-3">Update Expense</h2>
</div>
<div class="row">
<div class="col-12">
... BLABLABLA
</div>
</div>
</div>
</form>
And it works fine.
Now please DO NOT ask me why because I don't know, but if ANYONE has the answer to WHY? I'm all ears.

Insert data through a viewgrid after clicking on CREATE (more than one viewgrid)

I'm stuck on this situation and i dont understand how to make it works on MVC ASP.NET Core using C#
I created a viewgrid that allows me to Create, Update, Delete every single row shown in the grid. The problem is that everytime i click on CREATE it shows me a page where i can only write (manually) everything but instead of that i want my application to display another viewgrid (from a different database table) and allow the user to select the ROW or ROWS that he wants to add (something like a checkbox or whatever).
Take a look:
How can i do that?. I searched a lot but nothing really helped at all. Found something related to FORMS but not sure about that
This is my CONTEXT cs file:
public void CreateUser (User user)
{
using (SqlConnection con = new SqlConnection(connectionString))
{
SqlCommand cmd = new SqlCommand("Create_user", con)
{
CommandType = System.Data.CommandType.StoredProcedure
};
cmd.Parameters.AddWithValue("#NAME", user.NAME);
cmd.Parameters.AddWithValue("#LAST", user.LAST);
cmd.Parameters.AddWithValue("#DESCRIPTION", user.DESCRIPTION);
con.Open();
cmd.ExecuteNonQuery();
con.Close();
}
}
This is my Controller file:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create(int id, [Bind] User user)
{
try
{
if (ModelState.IsValid)
{
dbContext.UpdateAprobador(user);
return RedirectToAction("Index");
}
return View(dbContext);
}
catch
{
return View();
}
}
This is my VIEW file:
#model WebApplicationNewsan.Models.User
#{
ViewData["Title"] = "Create";
}
<h1>Create</h1>
<h4>User</h4>
<hr />
<div class="row">
<div class="col-md-4">
<form asp-action="Create">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="NAME" class="control-label"></label>
<input asp-for="NAME" class="form-control" />
<span asp-validation-for="NAME" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="LAST" class="control-label"></label>
<input asp-for="LAST" class="form-control" />
<span asp-validation-for="LAST" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="DESCRIPTION" class="control-label"></label>
<input asp-for="DESCRIPTION" class="form-control" />
<span asp-validation-for="DESCRIPTION" class="text-danger"></span>
</div>
<div class="form-group">
<input type="submit" value="Create" class="btn btn-primary" />
</div>
</form>
</div>
</div>
<div>
<a asp-action="Index">Back to List</a>
</div>
#section Scripts {
#{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}

Action Not Firing When Button Clicked

I have a Razor Index page with a button, that when clicked should run an action on the Home Controller, but when I debug the home controller, the action is not firing and the break point not being hit.
The Razor code is:
#{
ViewBag.Title = "csi media web test";
}
<div class="jumbotron">
<h1>csi media web test</h1>
<p class="lead">Liane Stevenson</p>
</div>
<div class="row">
<div class="col-md-12">
<div class="panel panel-info">
<div class="panel-heading"><i class="glyphicon glyphicon-arrow-right"></i> Enter Your Four Numbers</div>
<div class="panel-body">
<form class="form-inline">
<div class="col-md-9">
<div class="form-group">
<label class="sr-only" for="number1">1st Number</label>
<input type="number" class="form-control" id="number1" name="Number1" placeholder="#1">
</div>
<div class="form-group">
<label class="sr-only" for="number2">2nd Number</label>
<input type="number" class="form-control" id="number2" name="Number2" placeholder="#2">
</div>
<div class="form-group">
<label class="sr-only" for="number3">3rd Number</label>
<input type="number" class="form-control" id="number3" name="Number3" placeholder="#3">
</div>
<div class="form-group">
<label class="sr-only" for="number4">4th Number</label>
<input type="number" class="form-control" id="number4" name="Number4" placeholder="#4">
</div>
</div>
<div class="col-md-3 text-right">
<button class="btn btn-default" onclick="location.href='#Url.Action("SortDesc", "Home")'"><i class="glyphicon glyphicon-arrow-down"></i> Sort Desc</button>
<button class="btn btn-default" onclick="location.href='#Url.Action("SortAsc", "Home")'"><i class="glyphicon glyphicon-arrow-up"></i> Sort Asc</button>
</div>
</form>
<p>
#if (Model != null)
{
foreach (int number in Model.Numbers)
{
<span class="label label-info">#number</span>
}
}
</p>
</div>
</div>
</div>
</div>
And the Action is:
public ActionResult SortDesc (string number1, string number2, string number3, string number4)
{
NumberSetList list = new NumberSetList();
List<int> numbers = new List<int>();
numbers.Add(Convert.ToInt32(number1));
numbers.Add(Convert.ToInt32(number2));
numbers.Add(Convert.ToInt32(number3));
numbers.Add(Convert.ToInt32(number4));
numbers.OrderByDescending(i => i);
list.SortOrder = "Desc";
return View(list);
}
When it runs it does however change the URL of the page to:
http://localhost/Home/Index?number1=5&number2=4&number3=3&number4=9
So it's almost as if it knows the action is there and what it takes but it just doesn't run it?
What you need is a anchor tag and not a button. Having a link on a tag will actually change the browser URL to the value given in its href. Where as a button will do nothing. To change the URL you will have to add additional Javascript to handle it.
So change this
<button class="btn btn-default" onclick="location.href='#Url.Action("SortDesc", "Home")'">
<i class="glyphicon glyphicon-arrow-down"></i> Sort Desc
</button>
to
<a class="btn btn-default" href="#Url.Action("SortDesc", "Home")">
<i class="glyphicon glyphicon-arrow-down"></i> Sort Desc
</a>
Do the same changes to your other button syntax too.
This code is pseudo code and is untested but this should give you an idea
put this in your models folder
public class myViewModel
{
public int Number1 {get; set;}
public int Number2 {get; set;}
public int Number3 {get; set;}
public int Number4 {get; set;}
}
change your controller to something like this
[HttpPost]
public ActionResult SortDesc (myViewModel model)
{
if(!ModelState.IsValid)
{
return View(list)
}
else
{
NumberSetList list = new NumberSetList();
List<int> numbers = new List<int>();
numbers.Add(model.Number1);
numbers.Add(model.Number2));
numbers.Add(model.Number3));
numbers.Add(model.Number4));
numbers.OrderByDescending(i => i);
list.SortOrder = "Desc";
return View(list);
}
}
this will tell you if your model is valid or not, but I suspect your data is being passed and read as an integer rather than a string, so you could try changing the object type first and then try model binding
but on a review of my code just then, you might be missing the [HttpPost] attribute at the start of the code block which would mean this is always a HttpGet

Parsing a route parameter

Hello I am trying build a comment section for some physics articles in my site and for now i would like that when i click on
<a asp-route-articleid="smth" asp-action="Create">Create New</a>
it creates a page with url: http://localhost:65401/Physics/Create?articleid=smth
<h2>Create</h2>
<form asp-action="Create">
<div class="form-horizontal">
<h4>Physics</h4>
<hr />
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="CommentContext" class="col-md-2 control-label"></label>
<div class="col-md-10">
<input asp-for="CommentContext" class="form-control" />
<span asp-validation-for="CommentContext" class="text-danger" />
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Create" class="btn btn-default" />
</div>
</div>
</div>
</form>
and now my question: How would I go about extracting that articleid in my controller? So far i tried this
public async Task<IActionResult> Create([Bind("ID,CommentContext,UserName,ArticleID")] Physics physics, string articleid)
{
if (ModelState.IsValid)
{
physics.UserName = HttpContext.User.Identity.Name;
physics.ArticleID = articleid;
_context.Add(physics);
await _context.SaveChangesAsync();
return RedirectToAction("Index");
}
return View(physics);
}
and also other desperate attempts by no luck so far. Any help would be appreciated.
EDIT:
using HttpContext.Request.GetEncodedUrl();gets me http://localhost:65401/Physics/Create but the point is I need that articleid=smth value.
Solution:
Request.Headers["Referer"].ToString();
will return string of full url including that 'articleid=smth' value.
If I understand I problem then you have following problem.
You have Create Button on One Page and that generate link you described. http://localhost:65401/Physics/Create?articleid=smth
Now when you click that link Your create method get called and it will return View that you have specified. ( At this time if you look articleId in your method then it will have that value).
Now after you value in comment and you submit the form. At that time You will not able to find articleId. This is because articleId not preserve anywhere.
If above is your issue then following will solve your problem.
Solution.
In Controller create two method
Get Method that will called when you click Create New. Another one is called when you submit the form.
Controller
[HttpGet]
public async Task<IActionResult> Create(string articleId)
{
Physics t = new Physics();
if(!string.IsNullOrEmpty(articleId))
{
t.ArticleID = articleId;
}
return View(t);
}
[HttpPost]
public async Task<IActionResult> Create([Bind("ID,CommentContext,UserName,ArticleID")]Physics physics)
{
if (ModelState.IsValid)
{
physics.UserName = HttpContext.User.Identity.Name;
//_context.Add(physics);
//await _context.SaveChangesAsync();
return RedirectToAction("Index");
}
return View(physics);
}
In your view I have made small change so articleId will preserve. ( See I have created hidden field for articleId)
<h2>Create</h2>
<form asp-action="Create">
<div class="form-horizontal">
<input asp-for="ArticleID" type="hidden" />
<h4>Physics</h4>
<hr />
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="CommentContext" class="col-md-2 control-label"></label>
<div class="col-md-10">
<input asp-for="CommentContext" class="form-control" />
<span asp-validation-for="CommentContext" class="text-danger" />
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Create" class="btn btn-default" />
</div>
</div>
</div>
</form>
I hope that this solution will help you.

Categories

Resources