Updating an inner list using MongoDB - c#

I have an Object
public class Object1{
public List<Object2> {get;set;}
}
public class Object2{
public Name{get;set;}
public Address{get;set;}
}
I have a feature where the user can update just one instance of Object2. So my code for saving Object2 looks like
[HttpPost]
public ActionResult SaveObject2(Object2 obj2)
{
if (obj2.Id == null){
//Add Logic
obj1.Obj2List.Add(obj2)
}
else{
// Update logic
}
}
But obj2.Id is never null.Id is of type ObjectId. How can i check for logic to see if need to insert or update ? I am using asp.net MVC 3 and Mongo DB using the official C# drivers.
Thanks

The ObjectId type is a struct, not a class - so it's never going to be null. Check for ObjectId.Empty, instead.
A word of caution, though: I suppose that you are storing the id of Object2 in some hidden field between requests. If that is the case, be aware that malicious user can easily change the ID by using an HTTP proxy (such as Fiddler), thus tricking you into believing that the Object2 is being updated instead of added.
Depending on context of what you are trying to do, I would suggest performing some additional checks to more reliably determine if you should insert or update your object.

Related

C# OnDeserializing with Mongodb

I have a quick question. Is it possible to use MongoDB with the OnDeserializing attribute or something like that?
MongoClient client { get; } = new MongoClient("mongodb://localhost:27017");
var Userscollection = db.GetCollection<UserModel>("Users");
var userfind = (await Userscollection.FindAsync(x => x.UserId == "UserId"));
var user = userfind.FirstOrDefault();
My UserModel class has a function with the OnDeserializing attribute but it doesn't fire on Find and fetching the item of the user.
[OnDeserializing]
void TestFunc(StreamingContext context)
{
}
Is there any way to fire it automatically or any similar method to detect in the constructor of the class if the class is creating by my codes or using the MongoDB serializer/deserializer?
OK, After poking a lot with attributes and lots of tries finally I found a solution for my case.
I commented above that creating 2 constructors doesn't work because settings values are going to be done after running constructors.
But, There's a workaround! BsonConstructor Attribute
create a simple constructor or with arguments for your own (if you need otherwise you can skip it)
Then create another constructor but using the BsonConstructor attribute like below.
[BsonConstructor()]
public Postmodel(ObjectId postid, ObjectId userid)
{
//Called by the BSon Serialize/Deserialize
}
But surely this constructor will not be what you need because all of the properties are null or having default values so you need to pass some argument too.
The sample below will give you the values of properties you need so you can do whatever you want in the constructor.
[BsonConstructor(nameof(Id), nameof(UserId))]
public Postmodel(ObjectId postid, ObjectId userid)
{
}
Id and UserId are two properties in my class.
You can also simply use
[BsonConstructor("Id", "UserId")]
instead, But be careful, Changing properties name or removing them in the development won't notify you to fix your values, so using nameof(PropertyName) is much safer.

Entity Framework Checking Date in Class

I am using Entity Framework in an ASP.Net MVC Project. The point of the project was to create a web version of an existing older desktop project written in vb6. This vb6 project saves dates as 11/11/1911 whenever a blank date is needed to the table because I have been told by the vb6 programmer that vb6 dates cannot be set to null.
Obviously in my classes I have dates such as:
public DateTime? ExampleDate { get;set; }
This causes the field to appear as 11/11/1911 when ideally it should be null and despite my insistence to change vb6 to simply null the dates the programmer is telling me it can't be done. I know I can create manual properties in the class to check the field and return a value accordingly and mark it as [NotMapped] but there are a huge amount of dates across the tables and I don't want to be creating an extra property for every datetime nor do I want to be making a manual check in my code after loading a record and adding extra unnecessary code.
So what I would like to do if it's possible is somehow create my own datatype or method I can use in the class directly i.e. changing:
public DateTime? ExampleDate { get;set; }
To something like:
public CustomDateTime? ExampleDate { get;set; }
And have the CustomDateTime check and return accordingly. Can anyone tell me if this is possible or recommend another solution?
EDIT:
What about some kind of custom data attribute or similar?
[CustomDateTime]
public DateTime? ExampleDate { get;set; }
I tried with a custom validator but this only triggers on saving and I need to trigger the check when reading.
If you really can't modify the DB to have meaningful values, a good idea might be to have a DataAccess Objet and a Business Object.
I'm using this answer as a reference, How to map Data Access to Business Logic objects in Entity Framework. He explains the idea very well.
This will add some complexity to your code but your entities will stay clean. And, if later the DB values are updated and '11/11/1911' is replaced by NULL you will just need to update your mapping.
I would also recommend not adding additional fields for this purpose to your Entities, as you want to keep them clean. If you're stuck with the values in your database representing what you would consider a null DateTime value then I would employ an extension method.
This way you don't have to repeat your code and you can keep your entities clean... something like this:
namespace Project.DateTimeExtensions
{
public static class DateTimeExtensions
{
public static DateTime? FromVb6DateTime(this DateTime? dateTime)
{
// Is the DateTime a VB6 null representation, if so, return null
return (dateTime.ToString("dd/MM/yyyy") == "11/11/1911") ? dateTime : null;
}
}
}
The you can ensure that the values are converted to null under certain conditions:
// Using the extension namespace
using Project.DateTimeExtensions;
public class MyClass()
{
public IDataService DataService;
public MyClass(IDataService dataService)
{
this.DataService = dataService
}
public void MyMethod()
{
// Get the date time value however you would normally
var vb6DateTime = this.DataService.GetDate();
// Convert the value using the extension method
var convertedDateTime = vb6DateTime.FromVb6DateTime();
}
}

How to combine database access and cache in asp.net mvc (An object reference is required for the non-static field, method, or property 'Module.dbApp')

This is actually 2 questions in one.
I have an asp.net mvc application where I have to load a list of Modules, its just a simple list with ID, modulename and a class name to render it on the view with font awesome.
My model is like this:
public class Module
{
[Key]
public int Id { get; set; }
public string ModuleName { get; set; }
public string FontAwesomeClass { get; set; }
}
Because the module list is a Partial View that will render some icons on the top navigation bar, I dont want that for each refresh of the app, it goes to the DB, so it must be cached(I am using Azure REDIS Cache, not relevant for the question anyway), so instead of calling the DB context directly from the controller, I am calling a Cache Class that will check if the cache object exists, if not it will retrieve it from DB, if it does, it will return it from cache.
This my solution structure:
http://screencast.com/t/uayPYiHaPCav
Here is my controller Module.cs
public ActionResult GetModules()
{
return View(Cache.Module.GetModules());
}
As you can see the Controller does not have any logic where to get the data from.
Here is the Module.cs (on the Cache Namespace)
public class Module
{
private AppDataContext dbApp = new AppDataContext();
//Load modules from cache or from database
public static List<Models.Module> GetModules()
{
IDatabase cache = Helper.Connection.GetDatabase();
List<Models.Module> listOfModules = (List<Models.Module>)cache.Get("Modules");
if (listOfModules == null)
{
return dbApp.ModuleList.ToList();
}
else
{
return listOfModules;
}
}
}
Here I have a compiler error which I am not sure how to best fix it:
Error CS0120 An object reference is required for the non-static field,
method, or property 'Module.dbApp'
So that was my first question.
The 2nd question is more about the design pattern, do you consider this correct or not? the way I am trying to get the data from Cache, and its actually the Cache class which checks if data is on it or if it has to go to the DB.
First Question: make your private member static
private static AppDataContext dbApp = new AppDataContext();
2nd Question: your cache strategy seems pretty standard. The only thing is that you might want to expire cache data. For example, the cached data can get old and the longer it stays in the cache the older it gets. You might at some point want to expire it and get fresh data again.
Update:
#EstebanV for code sample (this off the top of my head, don't assume that it compiles):
/**
ICachedPersonDao abstracts away the caching mechanism
away from the core of your application
**/
public CachedPersonDao : ICachedPersonDao
{
private IPersonDao personDao = null;
public CachedPersonDao(IPersonDao personDao)
{
this.personDao = personDao;
}
public Person GetPersonById(int id){
bool isInCache = CACHE.SomeFunctionThatChecksInYourCache(id);
if (isInCache)
{
return CACHE.SomeFunctionThatReturnsTheCachedPerson(id);
}
else
{
//Well it's not in the cache so let's get it from the DB.
return this.personDao.GetPersonById(id);
}
}
}
/**
IPersonDao abstracts database communication
away from the core of your application
**/
public class PersonDao : IPersonDao
{
public Person GetPersonById(int id)
{
/** Get the person by id from the DB
through EntityFramework or whatever
**/
}
}
Usage:
In your controller, use ICachedPersonDao if you want to attempt to get from cache or use IPersonDao if you want to get it directly from the database without checking the cache.
Like I said, you should learn Dependency Injection it will help "inject" these dependencies into the classes that uses them.
I say again, this is off the top of my head. It won't compile. It's just to illustrate the concept.

How do I use WebAPI/Rest correctly when other params are needed

I am new to WebAPI and rest and am trying to do things correctly. By default if I were to access something such as User I would call api/user/5 if I wanted user 5. This would go to my User controller to Get(int num) I think. But I know I will often need other params passed as well. Currently I have Get(JObject data), but that data param is for other parameters. I will need other optional params whether I am sending an ID or wanting a list of everything. How do I go about organizing methods properly with WebAPI? Am I misunderstanding something?
To clarify:
This question is more about REST than dynamic objects, though they play a part:
How do I get a single resource vs a list of resources when I need additional params. I see those concepts as two separate methods, but the additional params complicate it in my mind when routing is involved.
Use attribute routing
For example -
[Route("customers/{customerId}/orders")]
public IEnumerable<Order> GetOrdersByCustomer(int customerId) { ... }
or
[Route("customers/{customerId}/orders/{orderId}")]
public Order GetOrderByCustomer(int customerId, int orderId) { ... }
if you need to return a list, create a method that returns a list, otherwise return the specific item requested
Look into using JToken or the even more dynamic 'dynamic' (Taken from here)
"
JSON and JavaScript is really dynamic, though, and often it's a hassle to try to "deserialize" really dynamic JSON objects into strongly-typed .NET structures. JSON.NET and ASP.NET Web API's model binding offer a happy medium - a middle ground - called JToken.
public class ContactController : ApiController
{
public JToken Post(JToken contact)
{
return contact;
}
}
Using JToken gives a dynamic container but also a DOM-like navigation model. But if that's not dynamic enough for me, why can't my method's parameter just take a "dynamic."
C# is statically typed, sure, but that doesn't mean I can't statically type something dynamic. ;)
Again, note the watch window.
Using dynamic to catch JSON post payloads
public class ContactController : ApiController
{
public dynamic Post(dynamic contact)
{
return contact;
}
}
"
I think you should make a new object for each WebAPI function that will handle the request. You can make the parameters optional with nullable properties.
[HttpPost]
public void SampleFunction(SampleFunctionModel model)
{
}
where SampleFunctionModel is:
public class SampleFunctionModel
{
public int? Id { get; set; }
public string Name { get; set; }
}

Converting an existing instance of a class to a more concrete subclass

Situation: I have a large shrink wrapped application that my company bought. It is supposed to be extensible, yada, yada. It has a DB, DAL and BLL in the form of SQL and DLLs. It also has a MVC project (the extensible part) but 95% of the "Model" part is in the DAL/BLL libraries.
Problem: I need to extend one of the "Models" located in the BLL. It is an User object with 47 properties, 0 methods and no constructor. What I started was a simple deivation of their class like:
public class ExtendedUser : BLL.DTO.User
{
public bool IsSeller { get; set; }
public bool IsAdmin { get; set; }
}
This works fine if I just create a new ExtendedUser. However, it is populated by another call into their BLL like:
BLL.DTO.User targetUser = UserClient.GetUserByID(User.Identity.Name, id);
I tried the straight forward brute force attempt, which of course throws a Cast Exception:
ExtendedUser targetUser = (ExtendedUser)UserClient.GetUserByID(User.Identity.Name, id);
I am drawing a complete blank on this very simple OO concept. I don't want to write a Constructor that accepts the existing User object then copies each of the properties into my extended object. I know there is a right way to do this. Can someone slap me upside the head and tell me the obvious?
TIA
If you do want to use inheritance, then with 47 properties, something like Automapper might help you copy all the values across - http://automapper.codeplex.com/ - this would allow you to use:
// setup
Mapper.CreateMap<BLL.DTO.User, ExtendedUser>();
// use
ExtendedUser extended = Mapper.Map<BLL.DTO.User, ExtendedUser>(user);
Alternatively, you might be better off using aggregation instead of inheritance - e.g.
public class AggregatedUser
{
public bool IsSeller { get; set; }
public bool IsAdmin { get; set; }
public BLL.DTO.User User { get; set; }
}
What about this approach (basically Aggregation):
public sealed class ExtendedUser
{
public ExtendedUser(BLL.DTO.User legacyUser)
{
this.LegacyUser = legacyUser;
}
public BLL.DTO.User LegacyUser
{
get;
private set;
}
}
I don't want to write a Constructor that accepts the existing User object then copies each of the properties into my extended object.
This is typically the "right" way to do this, unless you have compile time access to the BLL. The problem is that a cast will never work- an ExtendedUser is a concrete type of User, but every User is not an ExtendedUser, which would be required for the cast to succeed.
You can handle this via aggregation (contain the instance of the User as a member), but not directly via inheritance.
This is often handled at compile time via Partial Classes. If the BLL is setup to create the classes (ie: User) as a partial class, you can add your own logic into a separate file, which prevents this from being an issue. This is common practice with many larger frameworks, ORMs, etc.

Categories

Resources