Update my database - Failure - asp.net-mvc

Update: I debugged it several times and it seems that the 'UpdateUserDetails' function was fine, but I think the problem is in this line (within UpdateUser function):
var filter = Builders<User>.Filter.Eq("ID", input.ID);
I have a website (I have yet to upload it online), in which I use MongoDB on local host. I have USER SYSTEM (includes Login, Registration..). I tried to add an option to edit any registered user manualy by the admin, but I keep failing with updating the database with the new 'version' of the user.
The relevant code is attached..
~ The update function:
[HttpPost]
public ActionResult UpdateUser(User input)
{
// var a = input.ID;
var filter = Builders<User>.Filter.Eq("ID", input.ID);
var update = Builders<User>.Update
.Set("FirstName", input.FirstName)
.Set("LastName", input.LastName)
.Set("Phone", input.Phone)
.Set("Email", input.Email)
.Set("Password", input.Password)
.Set("Permission", input.Permission);
DBManager.UpdateUserDetails(filter, update);
ViewBag.Update = "Update successful";
return RedirectToAction("UsersList");
}
~ My DBManager class:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using MongoDB.Driver;
using MongoDB.Bson;
using MongoDB.Driver.Linq;
using SurffingSite.Models;
namespace SurffingSite.DB
{
public class DBManager
{
static MongoClient client;
static IMongoDatabase DB;
// Constractor
static DBManager()
{
client = new MongoClient("mongodb://localhost:27017");
DB = client.GetDatabase("HELLOSTACKOVERFLOW");
}
// Method to get list of all users//
public static IMongoCollection<User> GetUsersCollection()
{
var collection = DB.GetCollection<User>("User");
return collection;
}
internal static object GetCollection<T>(string v)
{
throw new NotImplementedException();
}
//User Method //
// Method for adding new user
public static void AddNewUser(User user)
{
var collection = DB.GetCollection<User>("User");
collection.InsertOne(user);
}
//Get user email.
public static User GetUserEmail(User input)
{
User email = DBManager.GetUsersCollection().Find(user => user.Email == input.Email).FirstOrDefault();
return email;
}
//Get user passsword.
public static User GetUserPassword(User input)
{
User password = DBManager.GetUsersCollection().Find(user => user.Password == input.Password).FirstOrDefault();
return password;
}
//User login verification
public static User UserVerification(User input)
{
// try get user by email
// if user exist than check if the password is correct if not than return null
User UseVar = DBManager.GetUserEmail(input);
if (UseVar != null && UseVar.Password == input.Password)
{
return UseVar;
}
return null;
}
//Update User details
public static void UpdateUserDetails(FilterDefinition<User> filter, UpdateDefinition<User> update)
{
var collection = DB.GetCollection<User>("User");
collection.UpdateOne(filter, update);
}
//Products Method's//
// Adding product into DB
public static void AddProduct(Products product)
{
var collection = DB.GetCollection<Products>("Products");
collection.InsertOne(product);
}
public static IMongoCollection<Products> GetProductsCollection()
{
var collection = DB.GetCollection<Products>("Products");
return collection;
}
// Find product in DB by ID
public static Products FindProductsById(Products input)
{
Products searchedProd = DB.GetCollection<Products>("Products").Find(product => product.Id == input.Id).FirstOrDefault();
return searchedProd;
}
//Update product
public static void UpdateDetails(FilterDefinition<Products> filter, UpdateDefinition<Products> update)
{
var collection = DB.GetCollection<Products>("Products");
collection.UpdateOne(filter, update);
}
//Orders//
// This method will return all exist orders
public static IMongoCollection<Orders> GetOrdersCollection()
{
var collection = DB.GetCollection<Orders>("Orders");
return collection;
}
//Place an new order
public static void AddOrder(Orders order)
{
var collection = DB.GetCollection<Orders>("Orders");
collection.InsertOne(order);
}
// Search for all user orders
public static List<Orders> FindUserOrders(User user)
{
List<Orders> searchedorders = DB.GetCollection<Orders>("Orders")
.Find(order => order.User.ID == user.ID).ToList<Orders>();
return searchedorders;
}
}
}
~ The User model:
using MongoDB.Bson;
using MongoDB.Bson.Serialization.Attributes;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Web;
namespace SurffingSite.Models
{
public class User
{
[Required]
[BsonId]
public ObjectId ID { get; set; }
[BsonElement("FirstName")]
public String FirstName { get; set; }
[BsonElement("LastName")]
public String LastName { get; set; }
[BsonElement("Phone")]
public String Phone { get; set; }
[BsonElement("Email")]
public String Email { get; set; }
[BsonElement("Password")]
public String Password { get; set; }
[BsonElement("Permission")]
public string Permission { get; set; }
}
}
I think the failure is within the 'Filter'...
THANKS IN ADVANCE

Related

Syncfusion Server-Side event is not passing data

I have a Asp.Net MVC project created from Syncfusion ASP.New MVC (Essential JS 2) VS template that is using Syncfusion's Data Grid. I can get the CrudUpdate event set in CrudUrl to fire at the server, however the value returned to CrudUpdate is empty. action parameter seems correctly set.
If I cast the value as Object, I get back a not-null, but VS cannot interrogate it. My guess is some weirdness in the way the value is cast or returned.
Has anyone got a complete working sample of the Syncfusion grid using the CrudUrl method with MVC (not asp). I am also guessing I may have some dependency issue.
View
#Html.EJS().Grid("CrudUrl").DataSource(dataManager => { dataManager.Url("/TestGrid2/UrlDatasource").CrudUrl("/TestGrid2/CrudUpdate").Adaptor("UrlAdaptor"); }).Columns(col =>
{
col.Field("RowKey").IsPrimaryKey(true).Add();
col.Field("PartitionKey").Add();
col.Field("sourceResourceId").Add();
col.Field("imagesLocation").Add();
col.Field("imagesResourceGroup").Add();
col.Field("imagePrefix").Add();
col.Field("imageVersion").Add();
}).AllowPaging().Toolbar(new List<string>() { "Search", "Add", "Edit", "Delete", "Update", "Cancel" }).EditSettings(edit => { edit.AllowAdding(true).AllowEditing(true).AllowDeleting(true); }).Render()
Controller
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Web.Http;
using System.Web.Mvc;
using System.Web.Script.Services;
using System.Web.Services;
using DB;
//using Microsoft.AspNetCore.Mvc;
using Syncfusion.EJ2.Base;
namespace VMSSManagmentConsole.Controllers
{
public class TestGrid2Controller : Controller
{
private ModelContainer db = new ModelContainer();
public ActionResult TestGrid2()
{
//var items = db.ManagementItems.ToList();
//ViewBag.dataSource = items;
return View();
}
public ActionResult UrlDatasource([FromBody]DataManagerRequest dm)
{
IEnumerable DataSource = db.ManagementItems.ToList();
DataOperations operation = new DataOperations();
int count = DataSource.Cast<ManagementItem>().Count();
if (dm.Skip != 0)
{
DataSource = operation.PerformSkip(DataSource, dm.Skip); //Paging
}
if (dm.Take != 0)
{
DataSource = operation.PerformTake(DataSource, dm.Take);
}
var result = (ActionResult)(dm.RequiresCounts ? Json(new { result = DataSource, count = count }) : Json(DataSource));
return result;
}
public ActionResult CrudUpdate([FromBody]ICRUDModel<ManagementItem> value, string action)
{
//if (value.action == "update")
//{
// var ord = value.value;
// ManagementItem val = db.ManagementItems.Where(or => or.RowKey == ord.RowKey).FirstOrDefault();
// val.imagePrefix = ord.imagePrefix;
// val.imagesLocation = ord.imagesLocation;
// val.imagesResourceGroup = ord.imagesResourceGroup;
// val.imageVersion = ord.imageVersion;
// val.sourceResourceId = ord.sourceResourceId;
//}
//else if (value.action == "insert")
//{
// db.ManagementItems.Add(value.value);
//}
//else if (value.action == "remove")
//{
// db.ManagementItems.Remove(db.ManagementItems.Where(or => or.RowKey == value.key.ToString()).FirstOrDefault());
// return Json(value);
//}
//return Json(value.value);
return null;
}
public class ICRUDModel<T> where T : class
{
public string action { get; set; }
public string table { get; set; }
public string keyColumn { get; set; }
public object key { get; set; }
public T value { get; set; }
public List<T> added { get; set; }
public List<T> changed { get; set; }
public List<T> deleted { get; set; }
public IDictionary<string, object> #params { get; set; }
}
}
}
Use the DataGrid scaffold wizard. On the third page select DataSourceType = "Remote Data". A page and controller will be created with the correct code.
For your reference, we have created a sample and perform CRUD actions. Please refer the attached sample for more information.
Sample: https://www.syncfusion.com/downloads/support/directtrac/general/ze/GridEJ2Mvc-914352281
The reported problem occurred when model mismatched. For Example, when we specify the number column field(EmployeeID) in grid but while inserting you did not specify the value for that column then it shows value as null in CrudUpdate, for this scenario you need to specify the nullable value for that field in model class as follows.
public class OrdersDetails
{
public OrdersDetails(int OrderID, string CustomerId, int EmployeeId, double Freight, bool Verified, DateTime OrderDate, string ShipCity, string ShipName, string ShipCountry, DateTime ShippedDate, string ShipAddress)
{
this.OrderID = OrderID;
this.CustomerID = CustomerId;
this.EmployeeID = EmployeeId;
. . . . .
}
public static List<OrdersDetails> GetAllRecords()
{
if (order.Count() == 0)
{
int code = 10000;
for (int i = 1; i < 10; i++)
{
order.Add(new OrdersDetails(code + 1, "ALFKI", i + 0, 2.3 * i, false, new DateTime(1991, 05, 15), "Berlin", "Simons bistro", "Denmark", new DateTime(1996, 7, 16), "Kirchgasse 6"));
. . . . .
}
}
return order;
}
public int? OrderID { get; set; }
public string CustomerID { get; set; }
public int? EmployeeID { get; set; } // it accept null value
. . . . .
}
}
If you still face the problem then share more details or below information that will helpful for us to validate further and provide a better solution as soon as possible.
• Did the problem occurred for both update and insert?
• Share package version details.
Regards,
Thavasianand S.

prevent duplicate users in online users list signalr

I am working on online users list. My code is:
public class User
{
public string id;
public string name;
public string dpExtension;
}
public class OnlineUsers : Hub
{
private Entities db = new Entities();
public static ConcurrentDictionary<string, User> users = new ConcurrentDictionary<string, User>();
public override System.Threading.Tasks.Task OnConnected()
{
User u = new User();
u.id = "visitor";
u.name = "Visitor";
u.dpExtension = "";
if (Context.User.Identity.IsAuthenticated)
{
u.id = Context.User.Identity.GetUserId();
var da = db.AspNetUsers.Find(u.id);
u.name = da.Email;
u.dpExtension = da.dpExtension;
}
User abc;
var data = users.TryGetValue(Context.ConnectionId, out abc);
if (!data)
{
users.TryAdd(Context.ConnectionId, u);
}
Clients.All.showConnected(users);
return base.OnConnected();
}
public override System.Threading.Tasks.Task OnDisconnected(bool stopCalled)
{
User abc;
users.TryRemove(Context.ConnectionId, out abc);
Clients.All.showConnected(users);
return base.OnDisconnected(stopCalled);
}
}
Now if the user has opened one browser tab, it is shown once in list and that's fine. But if user opens two tabs it is shown in list twice. How can I show one user only once in list?
You need to map ConnectionIds to one User. You can read a lot in this article - http://www.asp.net/signalr/overview/guide-to-the-api/mapping-users-to-connections .
I've added a few things in your code, you could see what was going on in this article:
public class User
{
public string dpExtension;
public string id;
public string name;
}
public class Map
{
public string UserId { get; set; }
public User User { get; set; }
public List<string> Connections { get; set; }
}
public class OnlineUsers : Hub
{
public static readonly List<Map> maps = new List<Map>();
private readonly Entities db = new Entities();
public override Task OnConnected()
{
var user = new User { id = "visitor", name = "Visitor", dpExtension = "" };
if (Context.User.Identity.IsAuthenticated)
{
user.id = Context.User.Identity.GetUserId();
var da = db.AspNetUsers.Find(user.id);
user.name = da.Email;
user.dpExtension = da.dpExtension;
}
Map data = maps.FirstOrDefault(t => t.UserId == user.id);
if (data == null)
{
maps.Add(new Map() {
UserId = user.id,
User = user,
Connections = new List<string>() { Context.ConnectionId }
});
}
else
{
data.Connections.Add(Context.ConnectionId);
}
Clients.All.showConnected(maps.Select(m => m.User));
return base.OnConnected();
}
public override System.Threading.Tasks.Task OnDisconnected(bool stopCalled)
{
var map = maps.FirstOrDefault(t => t.Connections.Contains(Context.ConnectionId));
if (map != null)
{
map.Connections.Remove(Context.ConnectionId);
if (map.Connections.Count <= 0)
{
maps.Remove(map);
}
}
Clients.All.showConnected(maps.Select(m => m.User));
return base.OnDisconnected(stopCalled);
}
}

Orchard cms apicontroller that returns xml

I've been trying to implement David Hayden's Orchard CMS and ASP .NET Web API http://www.davidhayden.me/blog/orchard-cms-and-asp.net-web-api, but I'm running into problems, basically getting a page not found.
This is what I have:
Under my controllers
ContactViewModel.cs
namespace Sunkist.ContactManager.Controllers
{
public class ContactsController : ApiController
{
private readonly IContentManager _contentManager;
public ContactsController(IContentManager contentManager)
{
_contentManager = contentManager;
}
public IEnumerable<ContactViewModel> Get()
{
return _contentManager
.Query(VersionOptions.Published, "Contact")
.List()
.Select(c => new ContactViewModel(c));
}
public ContactViewModel Get(int id)
{
var contact = _contentManager.Get(id);
if (contact == null)
throw new HttpResponseException
(new HttpResponseMessage(HttpStatusCode.NotFound));
return new ContactViewModel(contact);
}
}
}
ViewModel folder
ViewModel.cs
namespace Sunkist.ContactManager.ViewModel
{
public class ContactViewModel
{
private Orchard.ContentManagement.ContentItem c;
public ContactViewModel(Orchard.ContentManagement.ContentItem c)
{
// TODO: Complete member initialization
this.c = c;
}
public string Name { get; set; }
public string Address { get; set; }
public string City { get; set; }
}
}
and migration
namespace Sunkist.ContactManager {
public class Migrations : DataMigrationImpl {
public int Create() {
// Creating table ContactRecord
SchemaBuilder.CreateTable("ContactRecord", table => table
.ContentPartRecord()
.Column("Name", DbType.String)
.Column("Address", DbType.String)
.Column("City", DbType.String)
);
return 1;
}
}
}
I'm new to both Orchard and .Net MVC, So I'm not sure what I'm doing wrong?
Double check the name of the module that contains the Web API controller.
Via VS GUI, I created a new web api controller class "TestController.cs" and could not find the correct endpoint url.
That is, until I looked at the Module.txt in the project I added the controller to. The project is "Orchard.Users", but the name in the Module.txt file is just "Users".
I was able to hit the endpoint at "http://example.com/api/users/test".
Noteworthy: I setup a route for this at ".../UsersApi", but the 'auto-magic' URL pattern still works. Code below. Also, I later added a new module to contain my api controller and it would not work until I enabled the module in the dashboard.
TestController.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web.Http;
namespace Orchard.Users.Controllers
{
public class TestController : ApiController
{
// GET api/<controller>
public IEnumerable<string> Get()
{
return new string[] { "value1", "value2" };
}
// GET api/<controller>/5
public string Get(int id)
{
return "value";
}
// POST api/<controller>
public void Post([FromBody]string value)
{
}
// PUT api/<controller>/5
public void Put(int id, [FromBody]string value)
{
}
// DELETE api/<controller>/5
public void Delete(int id)
{
}
}
}
HttpRoutes.cs
using System.Collections.Generic;
using Orchard.Mvc.Routes;
using Orchard.WebApi.Routes;
public class HttpRoutes : IHttpRouteProvider
{
public void GetRoutes(ICollection<RouteDescriptor> routes)
{
foreach (RouteDescriptor routeDescriptor in GetRoutes())
{
routes.Add(routeDescriptor);
}
}
public IEnumerable<RouteDescriptor> GetRoutes()
{
return new[] {
new HttpRouteDescriptor {
Name = "UsersApi",
Priority = -10,
RouteTemplate = "usersapi/{id}",
Defaults = new {
area = "Orchard.Users",
controller = "Test",
id = RouteParameter.Optional
},
}
};
}
}

ViewModel in MVC correct way of accessing data

Can anyone please tell me whether this is the correct way of creating a viewmodel. I'm using Ninject and the only way I can get the view model to work is with the code below.
Also I cannot seem to be able to pass the data from the viewmodel to the controller unless I create a 2nd interface.
The code below does work, but reading all the examples I have seen I seem to be duplicating a lot off code from my domain layer.
---------------------Code Data access layer------
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.Data.SqlClient;
namespace Web.Domain.SearchEngine
{
public class DisplaySearchResults
{
public string Title { get; set; }
public string Description { get; set; }
public string URL { get; set; }
}
public class GetSearchResults : IGetSearchResults
{
private string dbConn;
public GetSearchResults()
{
dbConn = ConfigurationManager.ConnectionStrings["Search"].ConnectionString;
}
public IEnumerable<DisplaySearchResults> SearchResults(string q, string option, int pagenumber)
{
List<DisplaySearchResults> Data = new List<DisplaySearchResults>();
string spName = "dbo.FTS_On_at_Websites";
using (SqlConnection cn = new SqlConnection(dbConn))
{
using (SqlCommand cmd = new SqlCommand(spName, cn))
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add(new SqlParameter("#strSearchPhrase", SqlDbType.VarChar, 100));
cmd.Parameters.Add(new SqlParameter("#SearchMode", SqlDbType.Int, 4));
cmd.Parameters.Add(new SqlParameter("#intPageNumber", SqlDbType.Int));
cmd.Parameters.Add(new SqlParameter("#intRecordsPerPage", SqlDbType.Int));
cmd.Parameters.Add(new SqlParameter("#intTotalRecordsReturned", SqlDbType.Int));
cmd.Parameters["#strSearchPhrase"].Value = q;
cmd.Parameters["#SearchMode"].Value = 1;
cmd.Parameters["#intPageNumber"].Value = pagenumber;
cmd.Parameters["#intRecordsPerPage"].Value = 10;
cmd.Parameters["#intTotalRecordsReturned"].Value = 10;
cn.Open();
using (SqlDataReader rdr = cmd.ExecuteReader(CommandBehavior.Default))
{
if (rdr.HasRows)
{
while (rdr.Read())
{
Data.Add(new DisplaySearchResults
{
Title = (string)rdr["PageTitle"],
Description = (string)rdr["PageParagraph"],
URL = (string)rdr["PageURL"]
});
}
}
return Data;
}
}
}
}
}
}
-------------Code ViewModel--------------------
using Microsoft.Security.Application;
using System.Collections.Generic;
using System.Linq;
using Web.Domain.SearchEngine;
namespace Web.UI.ModelHelpers.Search
{
public class DisplaySearchResultsViewModel
{
public string Title { get; set; }
public string Description { get; set; }
public string URL { get; set; }
}
public class GetSearchResultsViewModel : IGetSearchResultsViewModel
{
private readonly IGetSearchResults _IGSR;
public GetSearchResultsViewModel(IGetSearchResults IGSR)
{
_IGSR = IGSR;
}
public IEnumerable<DisplaySearchResultsViewModel> SearchResultsViewModel(string q, string option, int pagenumber)
{
var searchResults = _IGSR.SearchResults(q, option, pagenumber).AsEnumerable();
List<DisplaySearchResultsViewModel> GetData = new List<DisplaySearchResultsViewModel>();
foreach (var details in searchResults.AsEnumerable())
{
GetData.Add(new DisplaySearchResultsViewModel()
{
Title = Sanitizer.GetSafeHtmlFragment(details.Title),
Description = Sanitizer.GetSafeHtmlFragment(details.Description).ToLower(),
URL = Sanitizer.GetSafeHtmlFragment(details.URL),
});
}
return GetData;
}
}
}
In controller I have
var DisplaySearchResults = _IGSR.SearchResultsViewModel(cleanText, "1", 1);
No, this is not the correct way to build a view model. A view model should not contain any data access logic in it. That's the responsibility of the model.
What you should do instead is use Ninject to inject the IGetSearchResults instance into your controller instead of having your GetSearchResultsViewModel view model take it as constructor dependency. Actually you do not need this GetSearchResultsViewModel at all. You already have the correct view model called DisplaySearchResultsViewModel. Then it's the responsibility of your controller to use your data access layer and build this view model.
For example:
public class SomeController : Controller
{
private readonly IGetSearchResults repository;
public SomeController(IGetSearchResults repository)
{
this.repository = repository;
}
public ActionResult SomeAction(string q, string option, int pagenumber)
{
// query your data access layer and build the view model that you will
// pass to the view
IEnumerable<DisplaySearchResultsViewModel> model = this.repository
.SearchResults(q, option, pagenumber)
.AsEnumerable()
.Select(details => new DisplaySearchResultsViewModel
{
Title = Sanitizer.GetSafeHtmlFragment(details.Title),
Description = Sanitizer.GetSafeHtmlFragment(details.Description).ToLower(),
URL = Sanitizer.GetSafeHtmlFragment(details.URL)
})
.ToList();
return View(model);
}
}

Entity framework savechanges error

I have a wizard step in which a user fills in fields. I then use json to save the values into my database for each wizard step.
However, in my repository I have my savechanges(). But it wont save the changes, instead it throws an error:
Entities in 'NKImodeledmxContainer.SelectedQuestion' participate in the 'QuestionSelectedQuestion' relationship. 0 related 'Question' were found. 1 'Question' is expected.
Anyone know how to get rid of the error? Do I have to get the ID from Question and save it aswell to my database or can I change something in EF so the error message is not getting thrown?
This is my post in my controller:
[HttpPost]
public JsonResult AnswerForm(int id, SelectedQuestionViewModel model)
{
bool result = false;
var goalCardQuestionAnswer = new GoalCardQuestionAnswer();
goalCardQuestionAnswer.SelectedQuestion = new SelectedQuestion();
goalCardQuestionAnswer.SelectedQuestion.Id = model.QuestionID;
goalCardQuestionAnswer.Comment = model.Comment;
goalCardQuestionAnswer.Grade = model.Grade;
if (goalCardQuestionAnswer.Grade != null)
{
answerNKIRepository.SaveQuestionAnswer(goalCardQuestionAnswer);
answerNKIRepository.Save();
result = true;
return Json(result);
}
answerNKIRepository.SaveQuestionAnswer(goalCardQuestionAnswer);
answerNKIRepository.Save();
return Json(result);
}
My Repository
public class AnswerNKIRepository
{
private readonly NKImodeledmxContainer db = new NKImodeledmxContainer();
public List<SelectedQuestion> GetAllSelectedQuestionsByGoalCardId(int goalCardId)
{
return db.SelectedQuestion.Where(question => question.GoalCard.Id == goalCardId).ToList();
}
public void SaveQuestionAnswer(GoalCardQuestionAnswer goalCardQuestionAnswer)
{
db.GoalCardQuestionAnswer.AddObject(goalCardQuestionAnswer);
}
public void Save()
{
db.SaveChanges();
}
}
This is my ViewModel:
public class SelectedQuestionViewModel
{
public int? Grade { get; set; }
public string Comment { get; set; }
public string SelectedQuestionText { get; set; }
public int QuestionID { get; set; }
}
This is my database model:
The exception complains that SelectedQuestion.Question is a required navigation property but you don't set this property in your code. Try to load the question by Id from the repository and set it to the SelectedQuestion.Question reference: Replace this line ...
goalCardQuestionAnswer.SelectedQuestion.Id = model.QuestionID;
...by...
goalCardQuestionAnswer.SelectedQuestion.Question =
answerNKIRepository.GetQuestionById(model.QuestionID);
And in your repository add the method:
public Question GetQuestionById(int id)
{
return db.Question.Single(q => q.Id == id);
}

Resources