Delete function doesn't work in MVC application-Does not delete from DB? - asp.net-mvc-5

I'm trying to make a delete function in my application that the user should be able to delete a product from the table but when the user presses the delete button, the error message "InvalidOperationException: Cannot remove an entity that has not been attached" comes up. I can't figure out what the problem is because it get's the product the user want's to delete(and displays it in the view) but when it get's to the HttpPost method, (when the user confirms that he want's to delete this product by pressing the delete button), the error message comes up... All the other methods work(create,edit,list...)only the delete method doesn't. I would really appreciate if someone can help me with this.
this is my code:
[HttpGet]
public ActionResult Delete(int id)
{
var p= prodRepo.GetProductById(id);
return View(p);
}
[HttpPost]
public ActionResult Delete(Product product)
{
prodRepo.DeleteProduct(product);
return RedirectToAction("Index");
}
this is the code from the productRepository class...
public Product DeleteProduct(Product product)
{
db = new NorthwindDataContext();
db.Products.DeleteOnSubmit(product);
db.SubmitChanges();
return product;
}
public Product GetProductById(int id)
{
db = new NorthwindDataContext();
var prod = (from p in db.Products
where p.ProductID==id
select p).Single();
return prod;
}

Just pass the id of product in delete action
[HttpPost]
public ActionResult DeleteConfirmed(int id)
{
Product_Table Ptobj = db.Product_Table.find(id);
db.Product_Table.remove(Ptobj);
db.savechanges()
}

Related

How Using tempdata to pass data entered by user in a data field from view to another view

I am new to MVC. I one please help me on how to assign value entered by user (for instance table column such as username) in a view to TempData.
I also want to pass the assigned data to a column in another view
In your view, add a form field:
<input name="myfield" type="text" />
In your controller's action, get the field and store it in TempData:
public ActionResult ProcessIt(string myfield)
{
TempData["yourkey"] = myfield;
return RedirectToAction("SomeOtherAction");
}
Now you can use it in the SomeOtherAction view:
<div>Entered data: #TempData["yourkey"]</div>
Thanks, I am creating web test, the controller for the question
public async Task Create([Bind(Include = "QuestionID,Question")]
TestQuestion testQuestion, string command, FormCollection QuestionData)
{
if (ModelState.IsValid)
{
db.TestQuestions.Add(testQuestion);
await db.SaveChangesAsync();
return RedirectToAction("Create", "TestOptions");
}
The controller for the options:
public async Task Create([Bind(Include = "OptionID,QuestionID,OptionA")] TestOption testOption)
{
if (ModelState.IsValid)
{
db.TestOptions.Add(testOption);
await db.SaveChangesAsync();
return RedirectToAction("Index");
}
ViewBag.QuestionID = new SelectList(db.TestQuestions, "", "", testOption.QuestionID);
return View(testOption);
}
I desire to display the question just entered by the user in the Create method of the option controller so that the user would enter the options for question.
The program create a dropdownlist of all the questions l've enter before, but I want only the last question should show in the redirected view.

update table in Azure Mobile Service

How to update particular record in azure mobile Service. For Example I have a table in azure called country having two columns
country_id
country_name
If I want to update the record with country_id=5 from USA to United State of America. How to Perform this.
//Global Variable
private MobileServiceCollection<country, country> items;
private IMobileServiceTable<country> todoTable = App.MobileService.GetTable<country>();
class country
{
public string id { get; set; }
public string country_name { get; set; }
public int country_id { get; set; }
}
private async void btnUpdate_Click(object sender, RoutedEventArgs e)
{
var change = await todoTable
.Where(todoItem => todoItem.country_name == tboxcName.Text)
.ToListAsync();
await todoTable.UpdateAsync(change);
}
The above code I tried from this post, but did not find out.
You might want to try this:
private async void btnUpdate_Click(object sender, RoutedEventArgs e)
{
var change = await todoTable
.Where(todoItem => todoItem.id.Equals(tboxcName.Text))
.ToListAsync();
if(change != null){
var toChange= change.First();
toChange.country_name="United State of America";
await todoTable.UpdateAsync(toChange);
}
else{
// you have nothing to change, you might throw an exception
}
}
In the textbox you should enter the id you want to update, in your case it's 5. Then I make a linq query selecting all the items with Id "5", this gets me a list.
I check if the list is not void, you would want to threat the case when the list is null. If it's not null I take the first element (as you are in the mobile services the id field is unique in the database, so you don't have to threat this boundary case (although if you really want to be sure it's always better to do it)).
The first element in the list will have the ID=5, so we change the object updating it's country name to "United States of America" (in your case, you don't care of the previous value, as you are updating a specific ID). Then you update this item. The mobile service API will then issue a patch request, and the database will patch it according to the Object ID.
Hope this helps!
Try with this C# code!
private async void btnUpdate_Click(object sender, RoutedEventArgs e)
{
var filteredRecords = await todoTable.Where(
todoItem => todoItem.country_id == 5)
.ToListAsync();
foreach (var item in filteredRecords)
{
item.country_name="United States of America";
await todoTable.UpdateAsync(item);
}
}

How to add Identity 2.0 users to an object

So I am trying to grasp EF6 and it's use of Identity 2.0 for making a many to many relationship. It is Visual Studio 2013 and the MVC 5 template.
I have a fresh MVC app with the following models:
public class Meeting
{
public Guid MeetingID { get; set; }
public string Title { get; set; }
public virtual ICollection<ApplicationUser> Attendees { get; set; }
}
public class ApplicationUser : IdentityUser
{
public ICollection<Meeting> Meetings { get; set; }
}
Then I scaffold a controller and views for Meetings. Now, for instance, if I just wanted to add every user as an attendee to my meeting, I would imagine that I could modify the Create action to look like the following:
public ActionResult Create(Meeting meeting)
{
if (ModelState.IsValid)
{
meeting.MeetingID = Guid.NewGuid();
db.Users.ForEachAsync(u => meeting.Attendees.Add(u));
db.Meetings.Add(meeting);
db.SaveChanges();
return RedirectToAction("Index");
}
else...
}
However I don't think it's working because I don't see it in my LocalDB and if I add this to the detail view for a meeting I get no results:
#{foreach (var item in Model.Attendees)
{
<li>#item.UserName</li>
}}
As a final note, I have two users in the LocalDB, test and test2.
What tutorial or documentation will allow me to make this work?
* Edit *
So I have tried your suggestion (I'll admit, I am unfamiliar with async and await and how to implement it), and I had to modify the controller to allow me to use await so I'm not sure if I'm doing this correctly now, but I got the following to compile and I get run time error of 'object reference not set to an instance of an object' :
public async Task<ActionResult> Create(Meeting meeting)
{
if (ModelState.IsValid)
{
meeting.MeetingID = Guid.NewGuid();
await db.Users.ForEachAsync(u => meeting.Attendees.Add(u));
db.Meetings.Add(meeting);
db.SaveChanges();
(is it possible I'm missing some setup of my model on Entity Framework? The project is exactly the code shown above plus defaults.)
You're going to kick yourself :)
(Drumroll)
You forgot to add await before your ForEachAsync line:
await db.Users.ForEachAsync(u => meeting.Attendees.Add(u));
Without await the application happily continues on and saves the record, all before that async process has completed.
UPDATE
Most likely you haven't initialized the Attendees collection. Just set it to a new List<ApplicationUser> in your constructor.

Is WCF Service EntitySetRights.AllRead Secure?

I have the following code inside MyDataService.svc.cs (This is an example from DevExpress):
namespace MyDataService {
[System.ServiceModel.ServiceBehavior(IncludeExceptionDetailInFaults = true)]
[JSONPSupportBehavior]
public class DataService : DataService<TestDataEntities>, IServiceProvider {
public static void InitializeService(DataServiceConfiguration config) {
config.SetEntitySetAccessRule("*", EntitySetRights.AllRead);
config.DataServiceBehavior.MaxProtocolVersion = DataServiceProtocolVersion.V3;
}
public object GetService(Type serviceType) {
if (serviceType == typeof(IDataServiceStreamProvider)) {
return new ImageStreamProvider();
}
return null;
}
protected override void OnStartProcessingRequest(ProcessRequestArgs args) {
CustomBasicAuth.Authenticate(HttpContext.Current);
if (HttpContext.Current.User == null)
throw new DataServiceException(401, "Invalid login or password");
base.OnStartProcessingRequest(args);
}
}
}
So while this is will check the Entity for a username and password, how safe is it that config.SetEntitySetAccessRule is set to AllRead. Wouldn't someone just be able to see this information on a url such as www.website.com/MyDataService.svc/Customer (where Customer is the table). If this is not so can someone please fill in the conceptual gap I am facing. Thanks!
You are correct that all entities will be returned when queried - AllRead just disallows insert updates and deletes.
You will need to use Query Interceptor to add your logic to restrict users to the set of data they have permission to view, for example adding a check user id to the query.

How to attach an existing View to a controller action?

How can I attach an existing View to an Action?
I mean, I've already attached this very View to an Action, but what I want is to attach to a second Action.
Example:
I've an Action named Index and a View, same name, attached to it, right click, add view..., but now, how to attach to a second one? Suppose an Action called Index2, how to achieve this?
Here's the code:
//this Action has Index View attached
public ActionResult Index(int? EntryId)
{
Entry entry = Entry.GetNext(EntryId);
return View(entry);
}
//I want this view Attached to the Index view...
[HttpPost]
public ActionResult Rewind(Entry entry)//...so the model will not be null
{
//Code here
return View(entry);
}
I googled it and cant find an proper answer...
It's possible?
you cannot "attach" actions to views but you can define what view you want be returned by an action method by using Controller.View Method
public ActionResult MyView() {
return View(); //this will return MyView.cshtml
}
public ActionResult TestJsonContent() {
return View("anotherView");
}
http://msdn.microsoft.com/en-us/library/dd460331%28v=vs.98%29.aspx
Does this help? You can use the overload of View to specify a different view:
public class TestController : Controller
{
//
// GET: /Test/
public ActionResult Index()
{
ViewBag.Message = "Hello I'm Mr. Index";
return View();
}
//
// GET: /Test/Index2
public ActionResult Index2()
{
ViewBag.Message = "Hello I'm not Mr. Index, but I get that a lot";
return View("Index");
}
}
Here is the View (Index.cshtml):
#{
ViewBag.Title = "Index";
}
<h2>Index</h2>
<p>#ViewBag.Message</p>

Resources