I am trying to get a user registered through a sign up page. When I am clicking register button an error shows syaing:
System.Data.SqlClient.SqlException: 'Cannot drop database "Officework" because it is currently in use.'
"Officework" is the name of my project.
I have made this project using code first approach. To make a distinction between business logic and database I have implemented repository.
This is were error is showing when I'm clicking on Register button:
public void InsertStudent(Population student)
{
context.Populations.Add(student);
}
This is my Sign Up controller:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult SignUp([Bind(Include = "Email,FirstName,LastName,MobileNumber,DateOfBirth,Password")] Population population)
{
if (ModelState.IsValid)
{
population.Password =password_hiding.encrypt(population.Password);
studentRepository.InsertStudent(population);
studentRepository.Save();
return RedirectToAction("SignIn");
}
return View(population);
}
The password_hiding is the object of the class ""Password", which I have used to encrypt password in database and decrypt it when showing to "User".
Password.cs class code
using System;
using System.IO;
using System.Security.Cryptography;
using System.Text;
namespace OfficeWork.ED
{
public class Password
{
public string encrypt(string clearText)
{
string EncryptionKey = "MAKV2SPBNI99212";
byte[] clearBytes = Encoding.Unicode.GetBytes(clearText);
using (Aes encryptor = Aes.Create())
{
Rfc2898DeriveBytes pdb = new Rfc2898DeriveBytes(EncryptionKey, new byte[] { 0x49, 0x76, 0x61, 0x6e, 0x20, 0x4d, 0x65, 0x64, 0x76, 0x65, 0x64, 0x65, 0x76 });
encryptor.Key = pdb.GetBytes(32);
encryptor.IV = pdb.GetBytes(16);
using (MemoryStream ms = new MemoryStream())
{
using (CryptoStream cs = new CryptoStream(ms, encryptor.CreateEncryptor(), CryptoStreamMode.Write))
{
cs.Write(clearBytes, 0, clearBytes.Length);
cs.Close();
}
clearText = Convert.ToBase64String(ms.ToArray());
}
}
return clearText;
}
public string Decrypt(string cipherText)
{
string EncryptionKey = "MAKV2SPBNI99212";
byte[] cipherBytes = Convert.FromBase64String(cipherText);
using (Aes encryptor = Aes.Create())
{
Rfc2898DeriveBytes pdb = new Rfc2898DeriveBytes(EncryptionKey, new byte[] { 0x49, 0x76, 0x61, 0x6e, 0x20, 0x4d, 0x65, 0x64, 0x76, 0x65, 0x64, 0x65, 0x76 });
encryptor.Key = pdb.GetBytes(32);
encryptor.IV = pdb.GetBytes(16);
using (MemoryStream ms = new MemoryStream())
{
using (CryptoStream cs = new CryptoStream(ms, encryptor.CreateDecryptor(), CryptoStreamMode.Write))
{
cs.Write(cipherBytes, 0, cipherBytes.Length);
cs.Close();
}
cipherText = Encoding.Unicode.GetString(ms.ToArray());
}
}
return cipherText;
}
}
}
The code of my model class
using System;
using System.ComponentModel.DataAnnotations;
using System.Data.Entity;
namespace OfficeWork.Models
{
public class Population
{
[Key]
public int ID { get; set; }
[Required]
[Display(Name ="Email")]
[EmailAddress(ErrorMessage ="Enter valid email address")]
public string Email { get; set; }
[StringLength(10)]
[Required]
[Display(Name = "First Name")]
public string FirstName { get; set; }
[StringLength(10)]
[Required]
[Display(Name = "Last Name")]
public string LastName { get; set; }
[Display(Name = "Mobile Number")]
[Required]
public long MobileNumber { get; set; }
[Display(Name = "Date Of Birth")]
[Required]
public DateTime DateOfBirth { get; set; }
[Display(Name = "Password")]
[Required]
[MaxLength(10000)]
public string Password { get; set; }
}
}
I also looked for the different kind of solution. One of them suggested to use Pooling=false in my connection string to close other connection, but it doesn't work in my case.
Here is my complete connection string:
<connectionStrings>
<add name="PopulationDBContext" connectionString="Data Source=ANIRUDH-PC\SQLEXPRESS;Initial Catalog=Officework;Integrated Security=True;Pooling=false;"
providerName="System.Data.SqlClient" />
</connectionStrings>
You need to replace the current Database Initialization Strategy, this sounds like you have the default DropCreateDataBaseAlways or the DropCreateDatabaseIfModelChanges strategy.
There are four different database initialization strategies:
CreateDatabaseIfNotExists: This is the default initializer. As the name suggests, it will create the database if none exists as per the configuration. However, if you change the model class and then run the application with this initializer, then it will throw an exception.
DropCreateDatabaseIfModelChanges: This initializer drops an existing database and creates a new database, if your model classes (entity classes) have been changed. So, you don't have to worry about maintaining your database schema, when your model classes change.
DropCreateDatabaseAlways: As the name suggests, this initializer drops an existing database every time you run the application, irrespective of whether your model classes have changed or not. This will be useful when you want a fresh database every time you run the application, for example when you are developing the application.
Custom DB Initializer: You can also create your own custom initializer, if the above do not satisfy your requirements or you want to do some other process that initializes the database using the above initializer.
This is usually declared in the constructor for your DbContext, but it can also be configred from a static initializer or in the app.config, the following is an example on how to remove the Db Initialization Strategy Altogether:
public partial class ConfigData : DbContext
{
static ConfigData()
{
//Database.SetInitializer(
// new System.Data.Entity.MigrateDatabaseToLatestVersion<ConfigData, Migrations.Configuration>());
Database.SetInitializer<ConfigData>(null);
SqlProviderServices.SqlServerTypesAssemblyName = typeof(SqlGeography).Assembly.FullName;
}
...
}
If you remove the strategy then you will be forced to manually call the EF update-database command from the package manager console, for small projects or singleton databases, this might be an option.
You can easily write your own strategy, say to only apply Upgrades:
public class CheckAndMigrateDatabaseToLatestVersionOnly<TContext, TMigrationsConfiguration>
: IDatabaseInitializer<TContext>
where TContext : DbContext
where TMigrationsConfiguration : DbMigrationsConfiguration<TContext>, new()
{
public virtual void InitializeDatabase(TContext context)
{
var migratorBase = ((MigratorBase)new DbMigrator(Activator.CreateInstance<TMigrationsConfiguration>()));
if (migratorBase.GetPendingMigrations().Any())
{
migratorBase.Update();
}
}
}
Then you could use that in the following change to the previous snippet:
Database.SetInitializer<ConfigData>(
new CheckAndMigrateDatabaseToLatestVersionOnly<ConfigData, Migrations.Configuration>());
Related
I am new to Umbraco CMS. I am using Ui-O-Matic plugin in my project.
Ui-O-Matic allows easy CRUD operation for database. But I want to use backoffice controls like file, textarea, etc.
So I am using UIOMaticFielld like this in database.cs file.
[Column("newsDetail")]
[UIOMaticField("News Detail","Add Details",View ="textarea")]
public string newsDetail { get; set; }
[Column("newsImage")]
[UIOMaticField("Image","Upload Image",View ="file")]
public string newsImage { get; set; }
Problem is when I make any change in database, I have to refresh database.tt file to get database changes. But it recreates database.cs file and my previous changes:
[UIOMaticField("News Detail","Add Details",View ="textarea")]
removes from database.cs file. And every time I have to do the same changes.
Please guide me what should I do to keep my custom changes as it is even I refresh database.tt file?
Other better way to do CRUD operation is also preferable.
After googling a lot, I found that as database.cs file is auto generated, I must not do custom changes in it.
I found another way to use backoffice controls. Let me explain here, may it will help to other.
Instead of writing UIOMatoicField in databse.cs file, create model to do the same.
Make below changes in "Models/Generated/database.tt" file
// Settings
ConnectionStringName = "umbracoDbDSN"; // Uses last connection string in config if not specified
Namespace = "Generator";
RepoName = "";
GeneratePocos = true;
ClassPrefix = "";
ClassSuffix = "";
// Read schema
var tables = LoadTables();
tables["Course"].Ignore = true; // Prevents table to include in databse.cs file
tables["News"].Ignore = true;
if (tables.Count>0)
{
#>
<## include file="UIOMatic.Generator.ttinclude" #>
<# } #>
Then create new Model as below. For ex. "Models\NewsModel.cs"
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using UIOMatic.Attributes;
using UIOMatic.Enums;
using UIOMatic.Interfaces;
using Umbraco.Core.Persistence;
using Umbraco.Core.Persistence.DatabaseAnnotations;
namespace EdumentUIOMatic.Models
{
[Umbraco.Core.Persistence.TableName("News")]
[PrimaryKey("newsId")]
[UIOMatic("News", "icon-box-open", "icon-box-open", RenderType = UIOMaticRenderType.List, ConnectionStringName = "umbracoDbDSN")]
public class NewsModel: IUIOMaticModel
{
[UIOMaticIgnoreField]
[Column("newsId")]
public int newsId { get; set; }
[Column("newsTitle")]
[UIOMaticField("News Title", "Add Title")]
public string newsTitle { get; set; }
[Column("newsDetail")]
[UIOMaticField("News Detail", "Add Details", View = "textarea")]
public string newsDetail { get; set; }
[Column("newsImage")]
[UIOMaticField("Image", "Upload Image", View = "file")]
public string newsImage { get; set; }
[Column("isDeleted")]
[UIOMaticField("Hide News", "Check if you want to hide this news")]
public bool isDeleted { get; set; }
[System.Web.Http.AcceptVerbs("GET", "POST")]
public IEnumerable<Exception> Validate()
{
return new List<Exception>();
}
}
}
Now if you will reload database.tt file to get updated database, your code will not be removed.
Is it possible in ASP.Net Core to automatically convert camel case property names in view models to insert spaces into the corresponding labels when using tag helpers?
If my view model looks like this...
[Display(Name = "First Name")]
public string FirstName { get; set; }
[Display(Name = "Last Name")]
public string LastName { get; set; }
[Display(Name = "Referral Date")]
public DateTime ReferralDate { get; set; }
It seems like a lot of extra configuration applying data annotations such as
[Display(Name = "First Name")]
to simply insert a space between words. It would make sense that Tag Helpers would insert the space by default to avoid this manual configuration and potential typos.
If not could a custom tag helper assist in this situation and if so how would it work?
If you only care about label, you can easily override LabelTagHelper.
[HtmlTargetElement("label", Attributes = "title-case-for")]
public class TitleCaseTagHelper : LabelTagHelper
{
public TitleCaseTagHelper(IHtmlGenerator generator) : base(generator)
{
}
[HtmlAttributeName("title-case-for")]
public new ModelExpression For { get; set; }
public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output)
{
if (context == null)
throw new ArgumentNullException("context");
if (output == null)
throw new ArgumentNullException("output");
string name = For.ModelExplorer.Metadata.DisplayName ?? For.ModelExplorer.Metadata.PropertyName;
name = name.Humanize(LetterCasing.Title);
TagBuilder tagBuilder = this.Generator.GenerateLabel(
this.ViewContext,
this.For.ModelExplorer,
this.For.Name,
name,
(object) null);
if (tagBuilder == null)
return;
output.MergeAttributes(tagBuilder);
if (output.IsContentModified)
return;
TagHelperContent childContentAsync = await output.GetChildContentAsync();
if (childContentAsync.IsEmptyOrWhiteSpace)
output.Content.SetHtmlContent((IHtmlContent) tagBuilder.InnerHtml);
else
output.Content.SetHtmlContent((IHtmlContent) childContentAsync);
}
}
Usage
<label title-case-for="RememberMe" class="col-md-2 control-label"></label>
Please ensure to place using statement and #addTagHelper inside _ViewImports.cshtml.
#using YourNameSpace.Helpers
#addTagHelper *, YourNameSpace
Note
I use Humanizer English Only NuGet Package - Humanizer.Core. It is more robust than writing my own method. If you doesn't like overhead, you can just use Regular Expression.
You can achieve this by building and registering a custom display metadata provider. There are libraries that will perform more elaborate "humanization" to the property names, but you can achieve something pretty useful with some trusty regular expressions.
public class HumanizerMetadataProvider : IDisplayMetadataProvider
{
public void CreateDisplayMetadata(DisplayMetadataProviderContext context)
{
var propertyAttributes = context.Attributes;
var modelMetadata = context.DisplayMetadata;
var propertyName = context.Key.Name;
if (IsTransformRequired(propertyName, modelMetadata, propertyAttributes))
{
modelMetadata.DisplayName = () => SplitCamelCase(propertyName);
}
}
private static string SplitCamelCase(string str)
{
return Regex.Replace(
Regex.Replace(
str,
#"(\P{Ll})(\P{Ll}\p{Ll})",
"$1 $2"
),
#"(\p{Ll})(\P{Ll})",
"$1 $2"
);
}
private static bool IsTransformRequired(string propertyName, DisplayMetadata modelMetadata, IReadOnlyList<object> propertyAttributes)
{
if (!string.IsNullOrEmpty(modelMetadata.SimpleDisplayProperty))
return false;
if (propertyAttributes.OfType<DisplayNameAttribute>().Any())
return false;
if (propertyAttributes.OfType<DisplayAttribute>().Any())
return false;
if (string.IsNullOrEmpty(propertyName))
return false;
return true;
}
}
The IsTransformRequired method ensures that you can still override the provider with a decorated property when you need to.
Register the provider on startup through the AddMvcOptions method on IMvcBuilder:
builder.AddMvcOptions(m => m.ModelMetadataDetailsProviders.Add(new HumanizerMetadataProvider()));
how about using a custom attribute and overriding DisplayNameAttribute
public class DisplayWithSpace : DisplayNameAttribute
{
public DisplayWithSpace([System.Runtime.CompilerServices.CallerMemberName] string memberName ="")
{
Regex r = new Regex(#"(?!^)(?=[A-Z])");
DisplayNameValue = r.Replace(memberName, " ");
}
}
and your property will be
[DisplayWithSpace]
public string FatherName { get; set; }
I am recently starting to learn mobile development for my Final Year Project, and I am doing an Android application using Xamarin.Android and Azure Mobile Services.
I have created a Test DB and created one entry there, trying to make my Android App to connect to the DB and retrieve this entry. I am doing this to get an idea how to establish a connection and retrieve data, and from there I will start modification properly.
That is how my Model class look like (note that JSON properties are named exactly like the columns names in my DB.
using Newtonsoft.Json;
namespace com.parkkl.intro.Models
{
class TestTable
{
public int Id { get; set; }
[JsonProperty(PropertyName = "UserName")]
public string UserName { get; set; }
[JsonProperty(PropertyName = "deleted")]
public bool Deleted { get; set; }
[JsonProperty(PropertyName = "version")]
public string Version { get; set; }
[JsonProperty(PropertyName = "createdAt")]
public string Creation { get; set; }
[JsonProperty(PropertyName = "updatedAt")]
public string Updated { get; set; }
}
}
And that is how my activity look like
using Android.App;
using Microsoft.WindowsAzure.MobileServices;
using Android.OS;
using com.parkkl.intro.Models;
using System.Collections.Generic;
using Android.Widget;
namespace com.parkkl.intro
{
[Activity(Label = "ParkKL", MainLauncher = false, Icon = "#drawable/icon")]
public class MainActivity : Activity
{
#region Variables
public static MobileServiceClient client = new MobileServiceClient
(#"http://parkkl.azurewebsites.net/");
private IMobileServiceTable<TestTable> test = null;
private List<TestTable> testItems;
#endregion
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
// Set our view from the "main" layout resource
SetContentView(Resource.Layout.Main);
test = client.GetTable<TestTable>();
testItems = new List<TestTable>();
GetData();
}
public async void GetData()
{
var collection = await test.Where(user => user.Id == 1).ToCollectionAsync();
foreach (var item in collection)
{
testItems.Add(
new TestTable
{
Id = item.Id,
UserName = item.UserName,
Deleted = item.Deleted,
Version = item.Version,
Creation = item.Creation,
Updated = item.Updated,
});
}
var finalItem = collection[0];
TextView text = (TextView)FindViewById(Resource.Id.TextFromDB);
text.Append(finalItem.UserName);
}
}
}
Now the issue is, every time I try to deploy the app, it throws this exception
Microsoft.WindowsAzure.MobileServices.MobileServiceInvalidOperationException:
You must be logged in to use this application
In my App Service in Azure, I have disabled all authentications, still I get this error. I am wondering where the issue is coming from?! I will much appreciate your help.
EDIT: I guess I found the issue, which was the permissions given on the table itself. However, I am still finding out a way to authenticate my app properly
Check out the book http://aka.ms/zumobook for details on how to deal with authentication.
I am making my project in MVC4, where i am using my Code first approach. i need to update my model
i have a following property which needs to be update , how can i achieve this
public class ContactForm
{
public char Phone { get; set; }
}
public class ConContext : DbContext
{
public DbSet<ContactForm> ContactForms { get; set; }
}
}
i want to update Phone propery to
public char Phone { get; set; }
thnx in advance, i have installed migrations to my projet already
My configuration.cs
namespace MyCRM.Migrations
{
using System;
using System.Data.Entity;
using System.Data.Entity.Migrations;
using System.Linq;
internal sealed class Configuration : DbMigrationsConfiguration<MyCRM.Models.ConContext>
{
public Configuration()
{
AutomaticMigrationsEnabled = false;
}
protected override void Seed(MyCRM.Models.ConContext context)
{
// This method will be called after migrating to the latest version.
// You can use the DbSet<T>.AddOrUpdate() helper extension method
// to avoid creating duplicate seed data. E.g.
//
// context.People.AddOrUpdate(
// p => p.FullName,
// new Person { FullName = "Andrew Peters" },
// new Person { FullName = "Brice Lambson" },
// new Person { FullName = "Rowan Miller" }
// );
//
}
}
}
The normal flow with EF code-first is too first update the model (a C# file) :
public class ContactForm
{
public string Phone { get; set; } //previously, this was let's say of type int
}
Then, you build your project and after that in the Package Manager Console, you have to call Add-Migration with some label (in order to rollback changes later if needed) :
Add-Migration Phone
This will add to your solution a file named like this 201409xxxxxxxx_Phone under the directory Migrations.
Then you have to put the changes to your database which can be done with the command (always in the console) :
Update-Database
Then, you should be done : the property Phone is of type string everywhere.
I am getting this error "Self referencing loop detected" while serializing using 'Json.NET'
I have a Book model
public class Book
{
public Book()
{
BookPersonMap = new List<BookPersonMap>();
}
public int BookId { get; set; }
public virtual ICollection<BookPersonMap> BookPersonMap { get; private set; }
(And many other virtual Icollections)
}
And this is the BookPerson Mapping class:
public class BookPersonMap
{
public int BookId { get; set; }
public string PersonName { get; set; }
public int PersonTypeId { get; set; }
public virtual Book Book { get; set; } // Foreign keys
public virtual PersonType PersonType { get; set; }
}
When I try to Serialize the Book object it throws:
"Self referencing loop detected for property 'Book' with type 'System.Data.Entity.DynamicProxies.Book_57F0FA206568374DD5A4CFF53C3B41CFDDC52DBBBA18007A896 08A96E7A783F8'. Path 'BookPersonMap[0]'."
I have tried the things suggested in some of the similar posts
Example:
PreserveReferencesHandling = PreserveReferencesHandling.Objects in Serializer settings returned a string with length 3 million!
ReferenceLoopHandling = ReferenceLoopHandling.Ignore in Serializer settings :
"An exception of type 'System.OutOfMemoryException' occurred in Newtonsoft.Json.dll but was not handled in user code"
^ Same luck with "ReferenceLoopHandling.Serialize"
MaxDepth = 1 : Infinite loop again.
Putting [JsonIgnore] on the virtual properties is working but it is a tedious task (because of numerous FK references) and not efficent, since if I miss one property and it will throw exception.
What is missing from above Json settings for them be not working?
services.AddMvc().AddJsonOptions(opt => {
opt.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore;
});
I have found the best way to solve this type of error is to flatten your model using a view model.
Put a break point on your object before it is serialized and start drilling into the child properties. You will probably find that you can go on indefinitely.
This is what the serializer is choking on.
Create a Constructor for your controller and put on it this line of code :
db.Configuration.ProxyCreationEnabled = false;
//db is the instance of the context.
For asp.net mvc 5 use this
Add the code below to your Application_Start method inside globax.asax file or startup file.
protected void Application_Start()
{
..
GlobalConfiguration.Configuration.Formatters.JsonFormatter
.SerializerSettings
.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore;
}
Disable lazy loading and
ensure your controller does not return
Json(..obj)
rather it should return
Ok(..obj)