ASP.net use session data to add something in create view - c#

I created this simple ASP.NET project. (Default template using MVC)
In there I generated models from my database using ADO.net
I also generated controller for my model. (The model generated functions for create, edit, delete...) I also got view for every function in the controller.
So what I am trying to do now is:
-I am in my create view. (that means I see my form for creating objects)
-I need to enter data for [title, content] but to post in database I also need an id (this id is a foreign key, not the id of the object i am creating)
I already have this id saved in my session. I can access the session data by doing:
var user = Session["user"] as Uporabniki; //returns session data
user.id //selects id from session
Now what I want is to use this id in the create form textbox.
As of now the rows for id in my view look like this (I have no idea why it's a dropdown list. When I open the site I see names of all users in database and I can select one. But this is not what I want. I want to see only one):
<div class="form-group">
#Html.LabelFor(model => model.id_avtorja, "id_avtorja", htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.DropDownList("id_avtorja", null, htmlAttributes: new { #class = "form-control" })
#Html.ValidationMessageFor(model => model.id_avtorja, "", new { #class = "text-danger" })
</div>
</div>
The create methods in controller look like this
// GET: Vprasanjas/Create
public ActionResult Create()
{
ViewBag.id_avtorja = new SelectList(db.Uporabniki, "id", "uporabniskoIme");
return View();
}
// POST: Vprasanjas/Create
// To protect from overposting attacks, please enable the specific properties you want to bind to, for
// more details see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create([Bind(Include = "id,naslov,vsebina,datum,id_avtorja")] Vprasanja vprasanja)
{
if (ModelState.IsValid)
{
db.Vprasanja.Add(vprasanja);
db.SaveChanges();
return RedirectToAction("Index");
}
ViewBag.id_avtorja = new SelectList(db.Uporabniki, "id", "uporabniskoIme", vprasanja.id_avtorja);
return View(vprasanja);
}
Why is it not working if I change the view to something like this:
<div class="form-group">
#Html.LabelFor(model => model.id_avtorja, "id_avtorja", htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#var user = Session["user"] as Uporabniki;
#Html.Raw(user.id)
#Html.ValidationMessageFor(model => model.id_avtorja, "", new { #class = "text-danger" })
</div>
</div>
And how can I fix this?

Try rewrite to
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create([Bind(Include = "id,naslov,vsebina,datum,id_avtorja")] Vprasanja vprasanja)
{
if (ModelState.IsValid)
{
vprasanja.id = (Session["user"] as Uporabniki).id;
db.Vprasanja.Add(vprasanja);
db.SaveChanges();
return RedirectToAction("Index");
}
ViewBag.id_avtorja = new SelectList(db.Uporabniki, "id", "uporabniskoIme", vprasanja.id_avtorja);
return View(vprasanja);
}
Main idea - assign your id on post.

Please post some info on the error. But my guess is you aren't creating any input HTML element so there's nothing posting. You need something like <input type="hidden" id="id_avtorja" value="#user.id"> in the form.
Also, I'd advise against using data out of a session variable. That's older technology and very un-MVC in philosophy.

Related

ASP POST ActionResult recieves a 0 instead of a provided ID value

Well, hello everyone.
I have a short ASP .NET MVC5 question. I have to pass a value from a ViewBag in the View method with a POST action result.
Create Method View Trigger
#Html.ActionLink("Add TestCase", "Create", "TestPlanTestCases", new { id = Model.TestPlan.ID }, null)
Controller Create GET method
public ActionResult Create(int id)
{
var testPlanFind = _db.TestPlan.Find(id);
ViewBag.TestPlanID = testPlanFind;
ViewBag.TestCaseID = new SelectList(_db.TestCase,"ID", "Name")
return View();
}
Create View, related DIV:
<div class="form-group">
#Html.LabelFor(model => model.TestPlanID, "TestPlanID", htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.ViewBag.TestPlanID.Name
#Html.ValidationMessageFor(model => model.TestPlanID, "", new { #class = "text-danger" })
</div>
Controller Create POST method
public ActionResult Create([Bind(Include = "TestPlanID,TestCaseID")] TestPlanTestCases testPlanTestCases)
{
if (ModelState.IsValid)
{
_db.TestPlanTestCases.Add(testPlanTestCases);
_db.SaveChanges();
return RedirectToAction("Details", "TestPlans", new {id = testPlanTestCases.TestPlanID});
}
ViewBag.TestCaseID = new SelectList(_db.TestCase, "ID", "Name", testPlanTestCases.TestCaseID);
ViewBag.TestPlanID = new SelectList(_db.TestPlan, "ID", "Name", testPlanTestCases.TestPlanID);
return View(testPlanTestCases);
So, my problem is, when the POST method is being called, the method always receives TestPlanID = 0 and TestCaseID = (ID of the chosen test case). I've used the same workaround for a different controller that has similar functionality and it works perfectly fine, but for some reason, when it comes to setting a predefined value such as TestPlanID it is automatically being set to 0, not even a null. The GET method works fine and passes the right ID, but when it comes down to the POST method, something goes wrong.
I hope I have provided enough information for you to understand the issue.
Thanks in advance!
Well. I've finally solved it, maybe not the best solution, but it works.
A dev friend of mine suggested parsing the URL to get the ID in the POST method. So I've decided to add 3 additional lines of code to the controller, first one to parse the URL for ID value, second to convert the string to Int32, and then assign the result value to the testPlanTestCases.TestPlan.
Updated Controller:
public ActionResult Create([Bind(Include = "TestCaseID")] TestPlanTestCases testPlanTestCases)
{
var testPlanId = RouteData.Values["id"];
testPlanId = Convert.ToInt32(testPlanId);
testPlanTestCases.TestPlanID = (int) testPlanId;
if (ModelState.IsValid)
{
_db.TestPlanTestCases.Add(testPlanTestCases);
_db.SaveChanges();
return RedirectToAction("Details", "TestPlans", new {id = testPlanTestCases.TestPlanID});
}
ViewBag.TestCaseID = new SelectList(_db.TestCase, "ID", "Name", testPlanTestCases.TestCaseID);
ViewBag.TestPlanID = new SelectList(_db.TestPlan, "ID", "Name", testPlanTestCases.TestPlanID);
return View(testPlanTestCases);

How to correctly recover date from SQL Server?

I created a simple CRUD using ASP.NET MVC and I can save my registers normally.
If I look in the Data Base my date was stored like that:
2017-06-01 00:01:23.750
But when I try to Edit the same register whith an async method created by MVC Scaffolding the date appears to bel null:
01/01/0001 00:00:00
Then (of course) I get an error:
The conversion of a datetime2 data type to a datetime data type
resulted in an out-of-range value.
Thats the async method:
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Edit([Bind(Include = "ArtigoId,Titulo,Texto,DataPublicacao,UltimaModificacao,UsuarioModificacao,DataCriacao,UsuarioCriacao")] Artigo artigo)
{
if (ModelState.IsValid)
{
db.Entry(artigo).State = EntityState.Modified;
await db.SaveChangesAsync();
return RedirectToAction("Index");
}
return View(artigo);
}
Why does it happen? How to correctly recover the date from data base?
EDIT:
I changed in Data Base for datetime2(0-7) but that made it accept the value 01/01/0001 00:00:00 and what I want is to know why this value appears instead of 2017-06-01 00:01:23.750.
All the others values in the data base is recovered normally, but not this date.
The problem occurred because I removed my field in the View and there is nothing to do with the date format in SQL Server.
I put the field back in the view as readyonly:
<div class="form-group">
#Html.LabelFor(model => model.DataCriacao, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.DataCriacao, new { htmlAttributes = new { #class = "form-control", #readonly = "readonly" } })
#Html.ValidationMessageFor(model => model.DataCriacao, "", new { #class = "text-danger" })
</div>
</div>
The search of the field in the DB is done in the GET method:
// GET: Artigos/Edit/5
public async Task<ActionResult> Edit(Guid? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
Artigo artigo = await db.Artigoes.FindAsync(id);
if (artigo == null)
{
return HttpNotFound();
}
return View(artigo);
}
The method I posted was POST after the submit of my button to save the changes and no searches were done on the database.

Confused on passing parameter to MVC Partial View?

I inherited an MVC site and was asked to combine two pages into one. Since both Views have their own View Model, I thought instead of pushing the two VMs together that I could use a Partial View to display, in this case, the Clock Group in a View called Clock_Detail. However, I need to get the GroupId to populate the data for the Clock Group.
So, having rarely used Partial Views I’m confused on how to get this to work.
I created a new View called _ClockGroup.cshtml and just copied and pasted some basic code from the other page just to see if I could get anything to display.
In my ClockDetail controller I added the following.
public PartialViewResult ClockGroup(int groupId)
{
ClockGroupViewModel vm = DAL.GetClockGroupDetail(groupId);
return PartialView(vm);
}
Here is _ClockGroup.cshtml
#model site.Models.ViewModels.ClockGroupViewModel
<div class="form-group">
#Html.LabelFor(m => m.GroupId, htmlAttributes: new { #class = "control-label col-md-2" })
#Html.EditorFor(m => m.GroupId, new { htmlAttributes = new { #class = "form-control", disabled = "disabled", #readonly = "readonly" } })
</div>
<div class="form-group">
#Html.LabelFor(m => m.GroupName, htmlAttributes: new { #class = "control-label col-md-2" })
#Html.EditorFor(m => m.GroupName, new { htmlAttributes = new { #class = "form-control", autofocus = "autofocus" } })
#Html.ValidationMessageFor(m => m.GroupName, "", new { #class = "text-danger" })
</div>
This is from the clock_detail.cshtml view. It uses the following Model and then I added the Partial to this view.
#model site.Models.ViewModels.ClockDetailViewModel
#Html.Partial("_ClockGroup")
Of course I get an error that the model passed a dictionary type “site.Models.ViewModels.ClockDetailViewModel” but the dictionary requires a model item of time “site.Models.ViewModels.ClockGroupViewModel".
Will I need to go ahead and combine the two ViewModels together and just use the single ViewModel?
When you do not specify an object as the second parameter:
#Html.Partial("_ClockGroup")
It automatically passes the current model which is of type ClockDetailViewModel
Your partial requires type ClockGroupViewModel
The fix would be when you call the partial to pass in the ClockGroupViewModel property of your ClockDetailViewModel object:
#Html.Partial("_ClockGroup", Model.ClockGroupViewModelProperty)
If your ClockDetailViewModel class does not have a ClockGroupViewModel property, you will need to add that to your ViewModel and populate the data.

How to post form data from razor view to WebApi as dictionary?

I have a lot of forms created with helper
Html.BeginRouteForm
I want to post it to my web api controller and I can do it with predefined DTO.
But I want to post it as dictionary, because the forms is for getting parameters from user. In each case the set of parameters can be different.
How I can do it?
How I can do it better?
Thanks!
UPDATE
Here is my form:
#using (Html.BeginRouteForm("DefaultApi", new { controller = "Products", action = "Add", httproute = "true" }))
{
<div class="form-group">
Product:
#Html.TextBoxFor(m => m.Product, new { #class = "form-control" })
</div>
<div class="form-group">
Cost:
#Html.TextBoxFor(m => m.Cost, new { #class = "form-control" })
</div>
}
You can declare the parameter in the post action as a FormDataCollection which is derived from NameValueCollection and is very similar to a dictionary. This is the weakly typed method to post form data in MVC.
[HttpPost]
public ActionResult Edit(FormDataCollection formDataCollection)
{
var nvc = formDataCollection.ReadAsNameValueCollection();
foreach(var key in nvc)
{
var value = nvc[key];
}
}

Insert date from view to controller

I am filling a form in "view" and sending it back to "controller" class.
In my database i want to add the date and time of user creation.
code in my view
<div class="form-group">
#Html.LabelFor(model => model.Ticket_CreationDate, new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Ticket_CreationDate)
#Html.ValidationMessageFor(model => model.Ticket_CreationDate)
</div>
</div>
code in controller class
public ActionResult Create([Bind(Include = "Ticket_SenderEmail,Ticket_Sujet,Ticket_Body,Ticket_CreationDate,Ticket_ClientID,Ticket_Priority,Ticket_UserID,Ticket_Status_ID")] Ticket ticket)
{
if (ModelState.IsValid)
{
db.Ticket.Add(ticket);
db.SaveChanges();
return RedirectToAction("Index");
}
ViewBag.Ticket_ClientID = new SelectList(db.Client, "Client_Id", "Client_Nom", ticket.Ticket_ClientID);
ViewBag.Ticket_Priority = new SelectList(db.Priority, "Priority_Id", "Priority_Name", ticket.Ticket_Priority);
ViewBag.Ticket_Status_ID = new SelectList(db.Ticket_Status, "Ticket_Status_Id", "Ticket_Status_Nom", ticket.Ticket_Status_ID);
ViewBag.Ticket_UserID = new SelectList(db.User, "User_Id", "User_Nom", ticket.Ticket_UserID);
return View(ticket);
}
My question is how i can send current datetime from view to controller ?
You won't send the date from the view, you will handle that in the controller...
yourdataentity newentity = new yourdataentity();
//the rest of your implementation may be a bit different, but this is one way to set the date for a new record...
newentity.createDate = DateTime.Now;
yourentitys.Add(newentity);
if (ModelState.IsValid)
{
db.yourentitys.Add(newentity);
db.SaveChanges();
}

Categories