PUT in MVC Single Page App Template creating new object? Why? - asp.net-mvc

I'm looking at the single-page web application for MVC4 from VS templates (from here http://www.asp.net/single-page-application) and it looks like the PUT action for ToDoLists is creating a new ToDoList - why is this? The code from the DTO class definition:
public TodoList ToEntity()
{
TodoList todo = new TodoList
{
Title = Title,
TodoListId = TodoListId,
UserId = UserId,
Todos = new List<TodoItem>()
};
foreach (TodoItemDto item in Todos)
{
todo.Todos.Add(item.ToEntity());
}
return todo;
}
From the controller:
public HttpResponseMessage PutTodoList(int id, TodoListDto todoListDto)
{
TodoList todoList = todoListDto.ToEntity();
db.Entry(todoList).State = EntityState.Modified;
db.SaveChanges();
return Request.CreateResponse(HttpStatusCode.OK);
}
So to update a record, we create a new one? I'm a little confused about how this is working - any clarification would be awesome.

In this example, the controller is converting the TodoListDto object into a TodoList object, which is the database object type. Since the DTO object is coming back from the web page, it has to be changed into the appropriate type so that Entity Framework can attach it to the DbSet and save changes.
ToEntity doesn't actually create a new record in the database, it creates a new TodoList instance which then gets attached, as modified to the database.

Related

Getting error when multiple results passing to view in asp.net MVC5

I use asp.net mvc 5 and EF 6 .I have following code in my controller
var resultOne = stats.GetPlayerStatsByParam(year, modeOne); //first
ViewData["more"] = stats.GetTeamStatsID(year); //second
return View("StatsNew", resultOne.ToList());
I am able to display result in view using "resultOne". Now I want to pass another data to same view using ViewData[]. its a stored procedure and the result is paasing to "ViewData["more"]".
I have done following code for "ViewData["more"]" in View page
But I am getting an error saying that 'object reference not set'
#foreach (var item in ViewData["more"] as #List<demo.GetTeamStatsID_Result>)
{
#item.Pld;
}
Use a viewmodel and extend it by the data coming from stats.GetTeamStatsID(year);
Do not use ViewBag or ViewData if not necessary for some reason (which I canĀ“t imagine right now)
As the comments have already pointed out, build a ViewModel class, that wraps everthing you need:
//I am using fake types here, sinceI don't know your model classes
//substitute accordingly!
public class MyViewModel
{
public PlayerStatsType PlayerStats { get; set;}
public List<demo.GetTeamStatsID_Result> Teams { get; set;}
}
Then in your action method:
var vm = new MyViewModel();
vm.PlayerStats = stats.GetPlayerStatsByParam(year, modeOne); //first
vm.TeamId = stats.GetTeamStatsID(year); //second
return View("StatsNew", vm);
Amend the model declaration in your view:
#model Namespace.Models.MyViewModel //again use namespace for your vm class
Now you can access both properties from your model:
#foreach (var item in Model.Teams)
{
#item.Pld;
}

Save model in session and use it in view

I've been looking at some of the answers on this site about saving model data to session but none seem to work for me, or most likely I am not understanding it correctly and not sure how to implement it.
This is the latest solution I've been trying.
c# - How to save object to session in ASP.NET
In the Index I get an error on declaring the model telling me User doesn't exist
Model
public class User
{
public int Id { get; set; }
public string Username { get; set; }
public string Password { get; set; }
}
Controller
public ActionResult Index()
{
using (DefaultConnection db = new DefaultConnection())
{
var model = from u in db.Users select u;
var vm = (User)Session["User"];
return View(vm);
}
}
View
#model User
#Model.Username
I am not quite sure what you are trying to achieve here. But i can see some problems in your code
var vm = (User)Session["User"];
You are trying to access a session variable with key User and trying to cast it to a User instance. That means, Before executing this code, you should be setting a valid user object to Session["User"]. If you do not do that, your casting will fail(code will crash) because Session does not have any item for the key "User"
If you haven't set it yet, Before accessing this session object, you should set a valid User object to session.
var us = new User { Id=1, Username="test"};
Session["User"] = us;
Later, before accessing from session item, you should always check whether it is null or not
User u = null;
if(Session["User"]!=null)
{
u = Session["User"] as User;
// you may use u now.
}
Also, you are querying from the Users table and selecting the records to the variable model. But you are not using that anywhere in your code. I am not sure why you want to do that.
I am not sure why you are using session. If you are trying to pass data between your action method to view, there are other better solutions like using a viewmodel (preferred), ViewBag etc.
Remember Session data is available across the entire application for the current session., not just one page. Use it wisely.
In order to save your model to the Session, you need to set the session object first e.g.
using (DefaultConnection db = new DefaultConnection())
{
var model = from u in db.Users select u;
Session["User"] = model; //Part where you set / save into the session
var vm = Session["User"] as User; //Part where you retrieve into the session
return View(vm);
}
User user = Session["User"] as User;
if ( user == null) user = new User();
If you want to access your ViewModel on the view, you can do it in many ways one way is to associate your view to a model (known as strongly typed views). You can do this in your view:
#model type #*Associate your view to a ViewModel, where type is your ViewModel Class*#
<h1>#Model.Name</h1> #*access the properties of your view using #Model *#
#model is used to associate a model to a view while #Model is used to access the associated model of a view. I suggest you read first on how ASP.NET MVC works. You may visit the ASP.NET MVC tutorial on views

MVC many to many delete

I have many to many relationship some tables. I am using entity framework.
Reservations >> ApartsToReservations << Aparts
ApartsToReservations include ReservationID and ApartID.
and my delete action below:
public ActionResult DeleteReservation(string resultId)
{
var result = Convert.ToInt32(resultId.Trim());
//just I have reservationID
return View();
}
How can delete reservation?
How can delete reservation?
For example:
[HttpPost] // <- should be a POST action because it's modifying data
public ActionResult DeleteReservation(string resultId)
{
var result = Convert.ToInt32(resultId.Trim());
//just I have reservationID
using (var context = new MyContext())
{
var reservation = new Reservation { ReservationID = result };
context.Reservations.Attach(reservation);
context.Reservations.Remove(reservation);
context.SaveChanges();
}
// ... redirect to Index or something, for example:
// return RedirectToAction("Index");
}
If you already have a context instance as a member of your controller class use this instead of creating a new one in the using block.
The code will also delete the related records in the ApartsToReservations link table because by default the relationships to this table are configured with cascading delete.
I'm not quite sure if this is what you are looking for because it actually doesn't matter if Reservation is involved in the many-to-many relationship you mentioned. It is just the (or one) standard way to delete an entity with DbContext.
If you are looking for something different please try to clarify your question or ask a new one which is clearer.

MVC 3 - Widget fine in Create action, but has null values in View action

I'm using ASP.NET MVC3, with Entity Framework.
I have a Widget controller, with standard Widget CRUD actions.
In my Create action, I successfully create a new Widget object, which has two FooBar objects. This is added to my database just fine, and the action the redirects to the View action.
[HttpPost]
public ActionResult Create(Widget model)
{
if (ModelState.IsValid)
{
//At this point, the widget has two FooBar properties. I can see the values for these FooBars just fine.
if (repo.AddWidget(model))
{
ViewBag.Message = "Your widget has been created.");
return RedirectToAction("View", new { id = model.Id });
}
else
{
ViewBag.Error = "Woops, something went wrong. Please try again.");
}
}
return View(model);
}
In the View action, I fetch the newly created Widget from my repository - except now the two FooBar properties are null.
public ActionResult View(int id)
{
var widget = repo.GetWidget(id);
if (widget == null)
{
ViewBag.Error = "No widget found for the specified ID";
return RedirectToAction("Find");
}
//At this point, the widget has two null values for the FooBar1 and FooBar 2 properties
return View(widget);
}
In the database itself I can see the correct FooBar ID values on my Widget.
My model is set up pretty much exactly the same as shown in this tutorial:
http://weblogs.asp.net/scottgu/archive/2010/07/16/code-first-development-with-entity-framework-4.aspx
public class WidgetContext : DbContext
{
public DbSet<Widget> Widgets { get; set; }
public DbSet<FooBar> FooBars { get; set; }
}
Can anyone suggest how I might start tracking this issue down?
Update:
I should clarify the values are null whenever I call the View action, not only after a Create.
Looks like FooBar is separate entity and FooBar1 and FooBar2 are navigation properties. In such case you must either explicitly say you want to loade them (we call this eager loading):
var widget = context.Widgets
.Include(w => w.FooBar1)
.Include(w => w.FooBar2)
.SingleOfDefault(w => w.Id == id);
Note: Strongly typed Include requires EF 4.1 for EFv1 or EFv4 use:
var widget = context.Widgets
.Include("FooBar1")
.Include("FooBar2")
.SingleOfDefault(w => w.Id == id);
or create custom strongly typed extension method like this.
or you must turn lazy loading on. Lazy loading makes separate queries to database once properties are first accessed in your view. It requires making both FooBar1 and FooBar2 virtual and context must be alive when view is rendered. Usually this is handled by singe context per HTTP request where context is for example created and disposed in custom controller factory or in custom Http module.
Also next time make your question complete please. You have shown a lot of code but the important parts (Windget class and GetById method) are missing. Unfortuanatelly users here aren't oracles so we need to now necessary details. Both action methods are almost irrelevant to your problem.

Invalid object name dbo.Categories

I am working on MVC 3. I am trying to create Simliar application as MVC Music Store but I am getting an error. My code is below:
using EFCodeFirst
BookDBContext _db = new BookDBContext();
[ChildActionOnly]
public ActionResult GenreMenu()
{
var categories = _db.Category.ToList();//**Giving error at this pointInvalid object name dbo.Categories**
return PartialView(categories);
}
Verify that your BookDBContext contains a property called Category and that your database contains table dbo.Categories.

Resources