Using JSON_QUERY as DbFunction in EF Core 6 - json

I am attempting to utilize SQL Server's built in JSON functionality with Entity Framework Core 6. It actually works exceedingly well with JSON_VALUE as shown below.
var results = _context.Pages.Where(p => MyDbFunctions.JsonValue(p._PublishedContent, "$.content").ToLower().Contains("test"));
DbContext is as follows:
public class JsonValueTestingContext : DbContext
{
public JsonValueTestingContext(DbContextOptions context) : base(context) { }
public DbSet<Page> Pages { get; set; }
public DbSet<Template> Templates { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.HasDbFunction(() => MyDbFunctions.JsonValue(default(string), default(string)));
modelBuilder.HasDbFunction(() => MyDbFunctions.JsonQuery(default(string), default(string)));
}
}
public static class MyDbFunctions
{
[DbFunction("JSON_VALUE", Schema = "", IsBuiltIn = true)]
public static string JsonValue(string source, [NotParameterized] string path) => throw new NotSupportedException();
[DbFunction("JSON_QUERY", Schema = "", IsBuiltIn = true)]
public static string JsonQuery(string source, [NotParameterized] string path) => throw new NotSupportedException();
}
The challenge I'm running into is that JSON_VALUE is good for basic types like string, int, boolean, datetime, etc. However, I do also store a string of arrays like ['Apple', 'Orange', 'Pear'] and I would very much like to do something similar to the following:
var results = _context.Pages.Where(p => MyDbFunctions.JsonQuery(p._PublishedContent, "$.content").Contains("Apple"));
I can't seem to figure out how to achieve the latter. If I try to return a string[] type for JSON_QUERY in MyDbFunctions, it says it is an invalid return type for the provider. I've tried all sorts of casting too, and Linq cannot translate. I feel like there must be a way.

The answer is to use OPENJSON, not JSON_QUERY in this scenario. On top of that there are some additional considerations. For example, you need to create a Keyless object with Key / Value attributes and specify IQueryable as the return type on the OPENJSON static method. See example below.
public class JsonValueTestingContext : DbContext
{
public JsonValueTestingContext(DbContextOptions context) : base(context) { }
public DbSet<Page> Pages { get; set; }
public DbSet<Template> Templates { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.HasDbFunction(() => MyDbFunctions.JsonValue(default(string), default(string)));
modelBuilder.HasDbFunction(() => MyDbFunctions.OpenJson(default(string), default(string)));
}
}
public static class MyDbFunctions
{
[DbFunction("JSON_VALUE", Schema = "", IsBuiltIn = true)]
public static string JsonValue(string source, [NotParameterized] string path) => throw new NotSupportedException();
[DbFunction("OPENJSON", Schema = "", IsBuiltIn = true)]
public static IQueryable<ArrayDatabaseItem> OpenJson(string source, [NotParameterized] string path) => throw new NotSupportedException();
}
[Keyless]
public class ArrayDatabaseItem
{
public int Key { get; set; }
public string Value { get; set; }
}
And usage may look like:
var results = _context.Pages.Where(p => MyDbFunctions.OpenJson(p._PublishedContent, "$.array_item").Any(c => c.Value == "Choice 2"));
#Charlieface's comment and this part of Microsoft Docs helped me arrive at the answer.

Related

EF Core and Pomelo 5.0 - how to query the json column

I'm using last version of json implementation in Pomelo 5.0 and configure my maria server to use microsoft json serialisation.
var serverVersion = new MariaDbServerVersion(new Version(10, 3, 0));
services.AddDbContext<BusinessManagementDbContext>(options =>
{
options.UseMySql(databaseConfiguration.ConnectionString, serverVersion, m =>
{
m.UseMicrosoftJson(MySqlCommonJsonChangeTrackingOptions.FullHierarchyOptimizedSemantically);
m.EnableRetryOnFailure();
});
options.EnableSensitiveDataLogging(true);
});
I can save my POCO in my db but when I try to query my data, I get a null object.
Here's my data :
HeidySQL data
My query is pretty simple but I think I'm not using the right way for json query.
await Context.ValidatedSaleInvoices.AsNoTracking().FirstOrDefaultAsync(x => x.Id == id);
It seems like there is no deserialization between my data and my property "Content".
How can I do this ?
Thank you,
Edit
My model is :
public class ValidateSaleInvoiceEntity
{
public int Id { get; set; }
public ValidateSaleInvoiceContent Content { get; set; }
}
public class ValidateSaleInvoiceContent
{
public string BusinessName { get; set; }
public DateTime Date { get; internal set; }
public string Number { get; internal set; }
public Address Address { get; internal set; }
public List<ValidateSaleInvoiceLineEntity> Lines { get; internal set; } = new List<ValidateSaleInvoiceLineEntity>();
}
public class ValidateSaleInvoiceLineEntity
{
public string Description { get; internal set; }
public decimal Quantity { get; internal set; }
public decimal UnitPriceVatExcluded { get; internal set; }
public decimal VatRate { get; internal set; }
}
And my json Result was like this (empty, like there waere no deserialisation: { "BusinessName":"", "Date":"", "Number":"" etc.}
My boss stop my poc about MariaDB Json implementation so I had to go back to this good old friend pure sql column :/ . That's why I haven"t a full json result. Sorry
For a property to serialize/deserialize JSON automatically to a POCO, you need to tell Pomelo, that the table column of the property is of the MySQL/MariaDB type json:
public class ValidateSaleInvoiceEntity
{
public int Id { get; set; }
[Column(TypeName = "json")] // <-- this is one way to do it
public ValidateSaleInvoiceContent Content { get; set; }
}
public class MyContext : DbContext
{
// ...
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<ValidateSaleInvoiceEntity>()
.Property(e => e.Content)
.HasColumnType("json"); // <-- this is another way to do it
}
}
Here is a fully working console project:
using System.ComponentModel.DataAnnotations.Schema;
using System.Diagnostics;
using System.Linq;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
namespace IssueConsoleTemplate
{
// EF Core entities:
public class IceCream
{
public int IceCreamId { get; set; }
public string Name { get; set; }
// Either use this data annotation, or the corresponding Fluent API call (see
// OnModelCreating), to explicitly mark the column type as JSON.
[Column(TypeName = "json")]
public IceCreamDetails Details { get; set; }
}
// JSON class:
public class IceCreamDetails
{
public int Kilojoule { get; set; }
public int Rating { get; set; }
}
public class Context : DbContext
{
public DbSet<IceCream> IceCreams { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
if (!optionsBuilder.IsConfigured)
{
var connectionString = "server=127.0.0.1;port=3306;user=root;password=;database=So68020732";
var serverVersion = ServerVersion.AutoDetect(connectionString);
optionsBuilder.UseMySql(connectionString, serverVersion, options => options
.UseMicrosoftJson(MySqlCommonJsonChangeTrackingOptions.FullHierarchyOptimizedSemantically))
.UseLoggerFactory(
LoggerFactory.Create(
configure => configure
.AddConsole()
.AddFilter(level => level >= LogLevel.Information)))
.EnableSensitiveDataLogging()
.EnableDetailedErrors();
}
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<IceCream>(
entity =>
{
// Either use this Fluent API call, or the corresponding data annotation
// (see the IceCreamDetails class), to explicitly mark the column type as JSON.
entity.Property(e => e.Details)
.HasColumnType("json");
entity.HasData(
new IceCream {IceCreamId = 1, Name = "Vanilla", Details = new IceCreamDetails { Kilojoule = 865, Rating = 9 }},
new IceCream {IceCreamId = 2, Name = "Chocolate", Details = new IceCreamDetails { Kilojoule = 903, Rating = 10 }});
});
}
}
internal static class Program
{
private static void Main()
{
using var context = new Context();
context.Database.EnsureDeleted();
context.Database.EnsureCreated();
var iceCreams = context.IceCreams
.OrderBy(i => i.IceCreamId)
.ToList();
Trace.Assert(iceCreams.Count == 2);
Trace.Assert(iceCreams[0].Details.Kilojoule == 865);
Trace.Assert(iceCreams[1].Details.Rating == 10);
}
}
}
You can find the most comprehensive JSON sample code on our repository (see the JSON mapping and query scenarios section).

jQuery Bootgrid - Ajax Sort Parameter with ASP.NET MVC Actions

I managed to create an ApiController retrieving data from my repositories, and populating a grid in my view through Bootgrid with Ajax. This is an example of request data sent to Api's Action, given by their Docs here (look for POST Body Request tab):
current=1&rowCount=10&sort[sender]=asc&searchPhrase=&id=b0df282a-0d67-40e5-8558-c9e93b7befed
Here is an example URL:
http://localhost/api/SomeController?current=1&rowCount=10&sort%5BName%5D=asc&searchPhrase=&id=b0df282a-0d67-40e5-8558-c9e93b7befed
I created two Helper classes to handle data I must return as response, and sort data (as it's an array):
public class SortData
{
public string Field { get; set; } // FIeld Name
public string Type { get; set; } // ASC or DESC
}
public class BootgridResponseData<T> where T: class
{
public int current { get; set; } // current page
public int rowCount { get; set; } // rows per page
public IEnumerable<T> rows { get; set; } // items
public int total { get; set; } // total rows for whole query
}
Therefore, my action is as follow:
public BootgridResponseData<SomeViewModel> Get(int current, int rowCount, List<SortData> sort, string searchPhrase, string id)
{
// get items and return a bootgrid response data with them...
}
The method is invoked and all parameters come with data properly, except sort, which is always null.
What kind of parameter should I expect for this? I also tried to put object but it comes null anyway.
After learning a bit more, I saw Bootgrid has a requestHandler setting which allows you to manipulate data sent to server.
I did it in my javascript like this:
var grid = $("#my-grid").bootgrid({
ajax: true,
rowCount: 10,
ajaxSettings: {
method: "POST",
cache: true
},
requestHandler: function (request) {
// Scan the original sort object from Bootgrid...
// and populate an array of "SortData"...
request.sortItems = [];
if (request.sort == null)
return request;
for (var property in request.sort) {
if (request.sort.hasOwnProperty(property)) {
request.sortItems.push({ Field: property, Type: request.sort[property] });
}
}
return request;
},
url: "/api/FooApi"
});
Then I created my post action in API like this:
public class FooApiController : ApiController
{
[HttpPost]
public BootgridResponseData<FooModel> Get(BootgridRequestData model)
{
// This would come from some data store, using the request params...
// I use PagedList to make pagination easier...
IPagedList<FooModel> itemsPaged = store.GetPagedFoo();
// Then return the response with data...
return new BootgridResponseData<FooModel>()
{
current = model.current,
rowCount = model.rowCount,
rows = itemsPaged,
total = itemsPaged.TotalItemCount
};
}
}
The BootgridResponseData has already been shown in my question. I just added a BootgridRequestData which the following structure:
public class BootgridRequestData
{
public int current { get; set; }
public int rowCount { get; set; }
public string searchPhrase { get; set; }
public IEnumerable<SortData> sortItems { get; set; }
}
Then I could even use my original SortData helper class:
public class SortData
{
public string Field { get; set; } // FIeld Name
public string Type { get; set; } // ASC or DESC
}
I've struggled with this as well. You are overthinking it. It's nice to create simple models to handle the post call from jquery-bootgrid, but you can also just use simple parameters in the post method. As for the sort, it looks like a Key-Value pair, but that doesn't serialize properly.
I ended up trying a Dictionary object and it works.
Here is my signature:
[HttpPost]
public async Task<ActionResult> GetActiveDogs(int? current, int? rowCount,
Dictionary<string, string> sort, string searchPhrase = null)
I had the same problem passing the sort options to my webservice. The Dictionary object did not solve my problem either.
To solve it, I created a class holding string properties for each field I wanted to pass through the bootgrid sort options. See code excerpt
class TestSort
{
public string field1 { get; set; }
public string field2 { get; set; }
...
}
I use this class as the sort options parameter in my webservice. All fields in this class that are referred to by the bootgrid options are set to "ASC" or "DESC". The others remain null.
I added an 'orderBy' property to this class that returns an orderby clause for the fields that are not null.
Approch1.
consider you have table with columns "col1, col2, col3, ...".
you can use:
public ActionType Get(int current, int rowCount, Sort sort, string searchPhrase) {
//sort.col1 == 'asc' (consider sorted by col1 in ascending order)
}
public class Sort
{
public string col1 { get; set; }
public string col2 { get; set; }
public string col3 { get; set; }
//... other columns
}
Approach 2.
You can use remove you parameters and parse request data manually. i used post here instead of get.
[HttpPost]
public object Post(){
string jsonContent = Request.Content.ReadAsStringAsync().Result;
Dictionary<string, string> keyvalues = new Dictionary<string, string>();
string[] keyvalue_strings = jsonContent.Split('&');
string sort_column = "";
string sort_direction = "";
for (var i = 0; i< keyvalue_strings.Length; i++)
{
var a = keyvalue_strings[i].Split('=');
a[0] = a[0].Replace("%5B", "[").Replace("%5D", "]");
keyvalues.Add(a[0], (a[1]));
if (a[0].Contains("sort"))
{
sort_column = a[0].Replace("sort[", "").Replace("]", "");
sort_direction = a[1];
}
}
//now you have keyvalues, sort_column, sort_direction.
//...
}

Service Stack POST-Request Body-Format / Transformation

iam using a RequestClass with the Route anotation to call a Json-Client POST method.
Now, while the paramters are structured like this
public class GetTicketRequest: IReturn<JsonObject>
{
public string CartId {
get;
set;
}
public string PriceId {
get;
set;
}
}
The BackendAPI needs them to be nesten in "data" in the json request, so more like
{
"data":[
{"cartid":123,
"priceId":11}]
}
Is there any way to transfrom the request object for the body before calling
JsonServiceClient _restClient = new JsonServiceClient(baseUrl);
JsonObject oneResponse = _restClient.Post(options);
This solution is useful where many DTOs require to be wrapped & converted, and is highly reusable, with no changes to your existing DTOs.
You can convert the requests of the JsonServiceClient by overriding the methods that handle preparing the requests for sending. Which means implementing your own extended JsonServiceClient as given below.
If you want to do this for all verbs then you override it's Send<TResponse> methods (otherwise, if it's just for POST then uncomment the commented out code, and remove the Send methods).
public class MyJsonServiceClient : JsonServiceClient
{
public Dictionary<Type, Func<object, object>> DtoConverters = new Dictionary<Type, Func<object, object>>();
public MyJsonServiceClient() {}
public MyJsonServiceClient(string baseUri) : base(baseUri) {}
public MyJsonServiceClient(string syncReplyBaseUri, string asyncOneWayBaseUri) : base(syncReplyBaseUri, asyncOneWayBaseUri) {}
public override TResponse Send<TResponse>(object request)
{
return base.Send<TResponse>(ConvertRequest(request));
}
public override TResponse Send<TResponse>(string httpMethod, string relativeOrAbsoluteUrl, object request)
{
return base.Send<TResponse>(httpMethod, relativeOrAbsoluteUrl, ConvertRequest(request));
}
/*
public override TResponse Post<TResponse>(string relativeOrAbsoluteUrl, object requestDto)
{
return base.Post(relativeOrAbsoluteUrl, ConvertRequest(requestDto));
}
*/
object ConvertRequest(object request)
{
Type dtoType = request.GetType();
return (DtoConverters.ContainsKey(dtoType)) ? DtoConverters[dtoType](request) : request;
}
}
Usage:
So given this DTO:
[Route("/test", "POST")]
public class TicketRequest : IReturnVoid
{
public string CartId { get; set; }
public string PriceId { get; set; }
}
You simply add the converter:
var client = new MyJsonServiceClient("http://localhost:9000");
// Simple converter for TicketRequest
client.DtoConverters.Add(typeof(TicketRequest), dto => {
var d = (TicketRequest)dto;
return new {
data = new {
CartId = d.CartId.ToInt(),
PriceId = d.PriceId.ToInt()
}
};
});
client.Post(new TicketRequest { CartId = "123", PriceId = "456" });
i solved this issue using a typed data property
public class GetTicketRequest: IReturn<JsonObject>
{
public class TicketCreateData
{
public int priceId {
get;
set;
}
}
public string CartId {
get;
set;
}
public string PriceId {
get;
set;
}
public List<TicketCreateData> data {
get {
var list = new List<TicketCreateData>();
list.Add(new TicketCreateData {
priceId = this.PriceId.ToInt()
});
return list;
}
set {
data = value;
}
}
}
To notes on this:
if neede, use DataContract/DataMember(Name="") to rename fields or only do partial serializing
Do never use structs for, like in this case, the data class - they are not serializeable at all
in my spefici case data even needs to be an array, thats why i used the list

Error in my code first approach i have EF 4.1 with VS 2010

1) i have Enttiy Class In which have three tables whose code is below given
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Data.Entity.ModelConfiguration;
using System.Linq;
using System.Web;
namespace GridWithInlineEdit.Models
{
#region ENTITY BLOCK
[Table("TBLUSER", Schema = "orient")]
public class Users
{
public Users()
{
UsersDetailCollection = new List<Usersdetail>();
}
//
[Key, Column("UID", TypeName = "INT")]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Uid { get; set; }
[Required]
[StringLength(50, MinimumLength = 10, ErrorMessage = "Please Enter {0} Upto 50 Characters!")]
[RegularExpression(#"(\S)+", ErrorMessage = "White space is not allowed here!")]
[Column("FNAME", TypeName = "nvarchar")]
public string Fname { get; set; }
[Required]
[StringLength(100, MinimumLength = 10, ErrorMessage = "Please Enter {0} Upto 50 Characters!")]
[RegularExpression(#"(\S)+", ErrorMessage = "White space is not allowed here!")]
[Column("LNAME", TypeName = "nvarchar")]
public string Lname { get; set; }
public ICollection<Usersdetail> UsersDetailCollection { get; set; }
}
[Table("TBLUSERDETAIL", Schema = "orient")]
public class Usersdetail
{
public Usersdetail()
{
CountryCollection = new List<Countries>();
}
[Key, Column("ID", TypeName = "INT")]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int ID { get; set; }
[StringLength(100)]
[Column("EMAIL", TypeName = "VARCHAR")]
public String Email { get; set; }
[StringLength(11)]
[Column("PHONE", TypeName = "VARCHAR")]
public String Phone { get; set; }
[Required]
public int? UserId { get; set; }
[ForeignKey("UserId"), Column("UID", TypeName = "INT")]
public virtual Users Users { get; set; }
[Required]
public int? CountryId { get; set; }
[ForeignKey("CountryId"), Column("CID", TypeName = "INT")]
public virtual Countries Countries { get; set; }
public ICollection<Countries> CountryCollection { get; set; }
}
[Table("TBLCOUNTRY", Schema = "orient")]
public class Countries
{
[Key, Column("CID", TypeName = "INT")]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Cid { get; set; }
[StringLength(50)]
[RegularExpression(#"(\S)+", ErrorMessage = "White space is not allowed here!")]
[Column("CNAME", TypeName = "VARCHAR")]
public String Cname { get; set; }
}
#endregion
#region ENTITY MAPPING BLOCK
public class UserMap : EntityTypeConfiguration<Users>
{
#region Constructors and Destructors
internal UserMap()
{
// Primary Key
HasKey(t => t.Uid);
Property(p => p.Uid).HasColumnName("UID").HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity).IsRequired();
// Table & Column Mappings
ToTable("TBLUSER");
Property(t => t.Fname).HasColumnName("FNAME").HasMaxLength(50);
Property(t => t.Lname).HasColumnName("LNAME").HasMaxLength(50);
}
#endregion
}
public class UserDetailMap : EntityTypeConfiguration<Usersdetail>
{
#region Constructors and Destructors
internal UserDetailMap()
{
// Primary Key
HasKey(t => t.ID);
HasKey(t => t.UserId);
HasKey(t => t.CountryId);
// Properties
Property(t => t.Email).HasMaxLength(100);
Property(t => t.Phone).HasMaxLength(11);
// Column Mappings
ToTable("TBLUSERDETAIL");
Property(t => t.ID).HasColumnName("ID").HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity).IsRequired();
Property(t => t.Email).HasColumnName("EMAIL");
Property(t => t.Phone).HasColumnName("PHONE");
Property(t => t.UserId).HasColumnName("UID");
Property(t => t.CountryId).HasColumnName("CID");
// Relationships
HasOptional(t => t.Users).WithMany().HasForeignKey(d => d.UserId);
HasOptional(t => t.Countries).WithMany().HasForeignKey(d => d.CountryId);
}
#endregion
}
public class CountryMap : EntityTypeConfiguration<Countries>
{
#region Constructors and Destructors
internal CountryMap()
{
// Primary Key
HasKey(t => t.Cid);
// Properties
Property(t => t.Cname).HasMaxLength(50);
// Column Mappings
Property(t => t.Cid).HasColumnName("CID").HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity).IsRequired();
Property(t => t.Cname).HasColumnName("CNAME");
}
#endregion
}
#endregion
}
2) Second is Init Class in which have connection string custom with sqlserver 2005
Connection string class code is below given
using System;
using System.Data.Common;
using System.Data.Entity.Infrastructure;
namespace GridWithInlineEdit.Models
{
public static class Constants
{
public static string ConnectionString
{
get { return GetDecryptedConnectionString(); }
}
private static string GetDecryptedConnectionString()
{
return #"Data Source=193.193.193.254;Initial Catalog=EFCFUsersdb;;USER ID=sa;PASSWORD=123;Persist Security Info=True";
}
}
class EncryptedIDbConnectionFactory : IDbConnectionFactory
{
#region Private Fields
IDbConnectionFactory _connectionFactory;
#endregion
#region Constructors
public EncryptedIDbConnectionFactory(IDbConnectionFactory dbConnectionFactory)
{
if (dbConnectionFactory == null)
{
throw new ArgumentNullException("dbConnectionFactory can not be null");
}
_connectionFactory = dbConnectionFactory;
}
#endregion
#region IDbConnectionFactory implementation
public DbConnection CreateConnection(string nameOrConnectionString)
{
//decryption of connection string
string decryptedConnectionString =
GetDecryptedConnectionString(nameOrConnectionString);
return _connectionFactory.CreateConnection(decryptedConnectionString);
}
#endregion
#region Private Methods
private string GetDecryptedConnectionString(string nameOrConnectionString)
{
//use some encryption library to decrypt
return nameOrConnectionString;
}
#endregion
}
}
and Init class is below given
using System.Data.Entity;
namespace GridWithInlineEdit.Models
{
public class Init : DropCreateDatabaseIfModelChanges<SampleContext>
{
protected override void Seed(SampleContext context)
{
base.Seed(context);
//context.Locations.Add(new Location() { LocationName = "Khanna, LDH" });
//context.Sessions.Add(new Session() { SessionName = "Entity Framework" });
context.SaveChanges();
}
}
}
3 ) this is samplecontext class code
using System.Data.Entity;
using System.Data.SqlClient;
namespace GridWithInlineEdit.Models
{
public class SampleContext : DbContext
{
public SampleContext()
: base(new SqlConnection(Constants.ConnectionString) ,false)
//Data Source=193.193.193.254;Initial Catalog=EFCFUsersdb;Persist Security Info=True;User ID=sa;Password=123
{
Configuration.ProxyCreationEnabled = true;
Configuration.AutoDetectChangesEnabled = true;
}
public DbSet<Users> User { get; set; }
public DbSet<Usersdetail> UserDetail { get; set; }
public DbSet<Countries> Country { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Configurations.Add(new UserMap());
modelBuilder.Configurations.Add(new UserDetailMap());
modelBuilder.Configurations.Add(new CountryMap());
}
}
}
4) in Global file of application have below code
using System.Data.Entity;
using System.Web.Mvc;
using System.Web.Routing;
using GridWithInlineEdit.Models;
namespace GridWithInlineEdit
{
// Note: For instructions on enabling IIS6 or IIS7 classic mode,
// visit http://go.microsoft.com/?LinkId=9394801
public class MvcApplication : System.Web.HttpApplication
{
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
filters.Add(new HandleErrorAttribute());
}
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "User", action = "Index", id = UrlParameter.Optional } // Parameter defaults
);
}
protected void Application_Start()
{
//Database.DefaultConnectionFactory = new EncryptedIDbConnectionFactory(Database.DefaultConnectionFactory);
Database.SetInitializer<SampleContext>(new Init());
AreaRegistration.RegisterAllAreas();
RegisterGlobalFilters(GlobalFilters.Filters);
RegisterRoutes(RouteTable.Routes);
}
}
}
In My Home Controller have below given code
> 1. using System.Web.Mvc; using GridWithInlineEdit.Models;
>
> namespace GridWithInlineEdit.Controllers {
> public class UserController : Controller
> {
>
>
> public ActionResult Index()
> {
> var db = new SampleContext();
> return View();
> }
>
> [HttpPost]
> public ActionResult Create()
> {
>
> //return View();
> return null;
> }
>
> } }
Now the problem is this whenever run my application database is not created and show exception server version property when i see through add watch in _db object by putting breakpoint on index action result.
pls pls resolve or give solution i have tried for this many time but i am confused why this happening
I know you have in the comments above that you applied a Windows Server patch and got it working, but with looking at your project, I had some observations:
There is nothing in your "Create" method in your controller for adding
new records
There is no "Read" method for returning data to anything
that might want to read data, such as a Kendo grid.
There is no "Delete" method for removing data records.
I'm not sure what the UserMap, DetailMap, and CountryMap are used for, along with your "RegisterRoutes", etc. on Application_Start -- these seem like a severe case of overcomplicating things, to me.
No View (presentation layer) code posted.
Maybe you fixed the Create, Read, and Delete routines later when you got it working, and maybe the UserMap, DetailMap, CountryMap, and Init all were for something, but be damned if I could make heads-or-tails of what you were doing. I saw no View code, grid or otherwise, that you were pulling your data into. When asking for help, just saying, context is everything.
While you would need to obtain and install Telerik's Kendo UI MVC components, it might be worth it to you to look at this blog for setting up the entity framework in MVC and preparing a grid for receiving data:
http://docs.telerik.com/kendo-ui/getting-started/using-kendo-with/aspnet-mvc/helpers/grid/ajax-binding

How to access property of generic type in linq expression

Iam using .NET 3.5. I have asp.net mvc app. There is base controller:
public abstract class BackendController<TModel> : BaseController where TModel : class
{
// skipped ...
public ActionResult BatchDelete(int[] ids)
{
var entities = repository.GetList().Where(item => ids.Contains(item.ID));
repository.delete(entities)
}
public ActionResult BatchHide(int[] ids)
{
var entities = repository.GetList().Where(item => ids.Contains(item.ID));
repository.BatchUpdate(
entities.Where(item => item.IsHidden == false),
c => new TModel { IsHidden = true }
);
}
}
It is won’t compile, because of item.ID and item.IsHidden - but in runtime this is valid type with certain properties. How to make this compile?
Well, you could use an interface to describe the common properties, and add a constraint to TModel:
public interface IModel
{
int ID { get; }
bool IsHidden { get; set; }
}
...
public abstract class BackendController<TModel> : BaseController
where TModel : IModel, new()