Executing an SP in EF Core - asp.net-core

I'm trying to execute an sp in ef core.
ALTER PROCEDURE [dbo].[usp_get_counts_for_event_type_for_single_date]
#OrgCode varchar(5),
#ProcessDate date
AS
BEGIN
SET NOCOUNT ON
DECLARE #StartTime time = '00:00:00'
DECLARE #EndTime time = '23:59:59'
DECLARE #PeriodStart datetime = CONVERT(datetime, #ProcessDate) + CONVERT(datetime, #StartTime)
DECLARE #PeriodEnd datetime = CONVERT(datetime, #ProcessDate) + CONVERT(datetime, #EndTime)
-- Insert statements for procedure here
SELECT CONVERT(VARCHAR(100), et.DisplayName) as Title,
et.DashboardColour as Colour,
count(et.EventTypeId) as Count
from EventType et
join EventLog el on et.EventTypeId = el.EventTypeId
WHERE el.StartTime BETWEEN #PeriodStart AND #PeriodEnd
group by et.DisplayName, et.DashboardColour
END
I have defined a data model class for the sp results.
public class GroupedCountResult
{
[Key]
[Column("varchar(100)")]
public string Title { get; set; }
[Column("varchar(20)")]
public string Colour { get; set; }
[Required]
public int Count { get; set; }
}
And then in DbContext.cs It's been added as a DbSet in the context
public DbSet<GroupedCountResult> GroupedCountResults { get; set; }
Then I try to execute it in an Core 2.2 MVC Controller. This is my weak point. I'm trying to chop the results up into strings that are then used in javascript for a pie chart. Hardcoded values until I get this working.
public async Task<ActionResult> Index()
{
StringBuilder sbLabels = new StringBuilder();
StringBuilder sbColours = new StringBuilder();
StringBuilder sbCounts = new StringBuilder();
string OrgCode = "HVO";
DateTime ProcessDate = new DateTime(2019, 08, 01); //.ToString("yyyyMMdd");
IEnumerable<GroupedCountResult> results = await _context.GroupedCountResults
.FromSql($"usp_get_counts_for_event_type_for_single_date #p0, #p1", OrgCode, ProcessDate)
.ToListAsync();
foreach(GroupedCountResult result in results) <--exception here
{
sbLabels.AppendFormat("'{0}',", result.Title);
sbColours.AppendFormat("'{0}',", result.Colour);
sbCounts.AppendFormat("{0},", result.Count);
}
ViewBag.Labels = sbLabels.ToString().TrimEnd(',');
ViewBag.Colours = sbColours.ToString().TrimEnd(',');
ViewBag.Counts = sbCounts.ToString().TrimEnd(',');
return View();
}
From the logs. I preferred the string interpolation version, but this seems closer to working.
Microsoft.EntityFrameworkCore.Database.Command:Information: Executed DbCommand (31ms) [Parameters=[#p0='?' (Size = 4000), #p1='?' (DbType = DateTime2)], CommandType='Text', CommandTimeout='30']
usp_get_counts_for_event_type_for_single_date #p0, #p1
I've worked through a few exceptions. It's now throwing an exception after the execution, implying there's something wrong with the results.
Microsoft.EntityFrameworkCore.Query:Error: An exception occurred while iterating over the results of a query for context type 'Ctrack.Dashboard.Data.DbContext'.
System.InvalidOperationException: The required column 'varchar(100)' was not present in the results of a 'FromSql' operation.
at Microsoft.EntityFrameworkCore.Query.Sql.Internal.FromSqlNonComposedQuerySqlGenerator.CreateValueBufferFactory(IRelationalValueBufferFactoryFactory relationalValueBufferFactoryFactory, DbDataReader dataReader)
at Microsoft.EntityFrameworkCore.Query.Internal.ShaperCommandContext.<NotifyReaderCreated>b__14_0(FactoryAndReader s)
at Microsoft.EntityFrameworkCore.Internal.NonCapturingLazyInitializer.EnsureInitialized[TParam,TValue](TValue& target, TParam param, Func`2 valueFactory)
at Microsoft.EntityFrameworkCore.Query.Internal.ShaperCommandContext.NotifyReaderCreated(DbDataReader dataReader)
at Microsoft.EntityFrameworkCore.Query.Internal.AsyncQueryingEnumerable`1.AsyncEnumerator.BufferlessMoveNext(DbContext _, Boolean buffer, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.SqlServer.Storage.Internal.SqlServerExecutionStrategy.ExecuteAsync[TState,TResult](TState state, Func`4 operation, Func`4 verifySucceeded, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.Query.Internal.AsyncQueryingEnumerable`1.AsyncEnumerator.MoveNext(CancellationToken cancellationToken)
at System.Linq.AsyncEnumerable.SelectEnumerableAsyncIterator`2.MoveNextCore(CancellationToken cancellationToken) in D:\a\1\s\Ix.NET\Source\System.Interactive.Async\Select.cs:line 106
at System.Linq.AsyncEnumerable.AsyncIterator`1.MoveNext(CancellationToken cancellationToken) in D:\a\1\s\Ix.NET\Source\System.Interactive.Async\AsyncIterator.cs:line 98
at Microsoft.EntityFrameworkCore.Query.Internal.AsyncLinqOperatorProvider.ExceptionInterceptor`1.EnumeratorExceptionInterceptor.MoveNext(CancellationToken cancellationToken)
System.InvalidOperationException: The required column 'varchar(100)' was not present in the results of a 'FromSql' operation.
at Microsoft.EntityFrameworkCore.Query.Sql.Internal.FromSqlNonComposedQuerySqlGenerator.CreateValueBufferFactory(IRelationalValueBufferFactoryFactory relationalValueBufferFactoryFactory, DbDataReader dataReader)
at Microsoft.EntityFrameworkCore.Query.Internal.ShaperCommandContext.<NotifyReaderCreated>b__14_0(FactoryAndReader s)
at Microsoft.EntityFrameworkCore.Internal.NonCapturingLazyInitializer.EnsureInitialized[TParam,TValue](TValue& target, TParam param, Func`2 valueFactory)
at Microsoft.EntityFrameworkCore.Query.Internal.ShaperCommandContext.NotifyReaderCreated(DbDataReader dataReader)
at Microsoft.EntityFrameworkCore.Query.Internal.AsyncQueryingEnumerable`1.AsyncEnumerator.BufferlessMoveNext(DbContext _, Boolean buffer, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.SqlServer.Storage.Internal.SqlServerExecutionStrategy.ExecuteAsync[TState,TResult](TState state, Func`4 operation, Func`4 verifySucceeded, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.Query.Internal.AsyncQueryingEnumerable`1.AsyncEnumerator.MoveNext(CancellationToken cancellationToken)
at System.Linq.AsyncEnumerable.SelectEnumerableAsyncIterator`2.MoveNextCore(CancellationToken cancellationToken) in D:\a\1\s\Ix.NET\Source\System.Interactive.Async\Select.cs:line 106
at System.Linq.AsyncEnumerable.AsyncIterator`1.MoveNext(CancellationToken cancellationToken) in D:\a\1\s\Ix.NET\Source\System.Interactive.Async\AsyncIterator.cs:line 98
at Microsoft.EntityFrameworkCore.Query.Internal.AsyncLinqOperatorProvider.ExceptionInterceptor`1.EnumeratorExceptionInterceptor.MoveNext(CancellationToken cancellationToken)
Exception thrown: 'System.InvalidOperationException' in System.Private.CoreLib.dll
Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker:Information: Executed action Ctrack.Dashboard.Controllers.HomeController.Index (Ctrack.Dashboard) in 1375.9283ms
Microsoft.AspNetCore.Routing.EndpointMiddleware:Information: Executed endpoint 'Ctrack.Dashboard.Controllers.HomeController.Index (Ctrack.Dashboard)'
Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware:Error: An unhandled exception has occurred while executing the request.
Has it lost track of the column name? I've tried converting the column to varchar(100). All the info on executing sp's implied it would be easier than this.

The problem lies in your model Data Annotation.If you would like to specify an exact data type for a column, you need to use [Column(TypeName = "varchar(100)")] instead of [Column("varchar(200)")] which will map the column name not column type
public class GroupedCountResult
{
[Key]
[Column(TypeName ="varchar(100)")]
public int Title { get; set; }
[Column(TypeName = "varchar(20)")]
public string Colour { get; set; }
}
Refer to
https://learn.microsoft.com/en-us/ef/core/modeling/relational/data-types
https://learn.microsoft.com/en-us/ef/core/modeling/relational/columns

Here is how i am calling my stored procedure in .net core
public class DbUtilities
{
private readonly ILogHandler _oisLogger;
private readonly SB1_VVFContext _context;
public DbUtilities(ILogHandler oislogger, SB1_VVFContext context)
{
_oisLogger = oislogger;
_context = context;
}
public IEnumerable<VehicleSearchResultDTO> SearchVehicleRecords(VehicleSearchCriteriaDTO Criteria)
{
List<VehicleSearchResultDTO> result = new List<VehicleSearchResultDTO>();
VehicleSearchResultDTO vehRec = null;
try
{
//Define Command Object
_context.Database.OpenConnection();
DbCommand cmd = _context.Database.GetDbConnection().CreateCommand();
SqlParameter refnum = new SqlParameter("#RefNum", SqlDbType.VarChar, 10)
{
Direction = ParameterDirection.Input,
Value = (!string.IsNullOrWhiteSpace(Criteria.RefNum)) ? Criteria.RefNum : string.Empty
};
//Define Input parameters
SqlParameter vin = new SqlParameter("#Vin", SqlDbType.VarChar, 100)
{
Direction = ParameterDirection.Input,
Value = (!string.IsNullOrWhiteSpace(Criteria.Vin)) ? Criteria.Vin : string.Empty
};
SqlParameter owner = new SqlParameter("#Owner", SqlDbType.VarChar, 200)
{
Direction = ParameterDirection.Input,
Value = (!string.IsNullOrWhiteSpace(Criteria.RegisteredOwner)) ? Criteria.RegisteredOwner : string.Empty
};
SqlParameter plate = new SqlParameter("#Plate", SqlDbType.VarChar, 10)
{
Direction = ParameterDirection.Input,
Value = (!string.IsNullOrWhiteSpace(Criteria.Plate)) ? Criteria.Plate : string.Empty
};
SqlParameter email = new SqlParameter("#Email", SqlDbType.VarChar, 200)
{
Direction = ParameterDirection.Input,
Value = (!string.IsNullOrWhiteSpace(Criteria.Email)) ? Criteria.Email : string.Empty
};
SqlParameter VehicleReviewStatusId = new SqlParameter("#VehicleReviewStatusId", SqlDbType.Int)
{
Direction = ParameterDirection.Input,
Value = Criteria.VehicleReviewStatusId
};
//Define properties for command object and execute the SP
cmd.CommandText = "usp_Vehicle_Search_Result";
cmd.Parameters.Add(refnum);
cmd.Parameters.Add(vin);
cmd.Parameters.Add(owner);
cmd.Parameters.Add(plate);
cmd.Parameters.Add(email);
cmd.Parameters.Add(VehicleReviewStatusId);
cmd.CommandTimeout = 10;
cmd.CommandType = CommandType.StoredProcedure;
DbDataReader reader = cmd.ExecuteReader();
if (reader.HasRows)
{
//Get Search Result
while (reader.Read())
{
vehRec = new VehicleSearchResultDTO
{
VehicleID = (Guid)reader["VehicleId"],
ReferenceNumber = reader["ReferenceNumber"].ToString(),
SubmitterEmail = reader["EmailAddress"].ToString(),
Status = reader["StatusName"].ToString(),
SubmittedDate = CheckNull<DateTime?>(reader["DateSubmitted"]),
VIN = reader["VIN"].ToString(),
Year = CheckNull<int>(reader["Year"]),
Make = reader["Make"].ToString(),
LicensePlate = reader["LicensePlate"].ToString(),
ROName = reader["ROName"].ToString(),
StatusColor = reader["StatusColor"].ToString()
};
result.Add(vehRec);
}
}
else
{
result = null;
}
}
catch (Exception ex)
{
_oisLogger.LogError(2205, $"ERROR SearchVehicleRecords", ex);
}
finally
{
_context.Database.CloseConnection();
}
return result;
}
Here is the input object:
public class VehicleSearchCriteriaDTO
{
public VehicleSearchCriteriaDTO()
{
}
[Display(Name = "Ref#")]
public string RefNum { get; set; }
[Display(Name = "VIN")]
public string Vin { get; set; }
[Display(Name = "Reg Owner")]
public string RegisteredOwner { get; set; }
[Display(Name = "Plate")]
public string Plate { get; set; }
[Display(Name = "Email")]
public string Email { get; set; }
public int VehicleReviewStatusId { get; set; }
}
Here is the output object:
public class VehicleSearchResultDTO
{
[Display(Name = "Owner")]
public string ROName { get; set; }
[Display(Name = "RefNum")]
public string ReferenceNumber { get; set; }
[Display(Name = "VIN")]
public string VIN { get; set; }
[Display(Name = "Plate")]
public string LicensePlate { get; set; }
[Display(Name = "Year")]
public int Year { get; set; }
[Display(Name = "Make")]
public string Make { get; set; }
[Display(Name = "Submitter Email")]
public string SubmitterEmail { get; set; }
[Display(Name = "Submitted Date")]
public DateTime? SubmittedDate { get; set; }
[Display(Name = "Status")]
public string Status { get; set; }
public Guid VehicleID { get; set; }
public string StatusColor { get; set; }
}
I did not add these classes to the dbcontext or the proc to the dbcontext. Also, i would suggest you comment your code out to only fetch one result variable at a time.
See if the mapping to the object from the SP call works well, then add another variable/parameter.

Related

is there a reason to serialize and then deserialize an object?

I have a SOAP web service that someone developed at my work place and i try to learn it and i came across a move in the code that i can't get my head around. can someone explain to me the logic behind it? why would someone want to serialize an object and a line after to deserialize it?
**this is the whole code: if someone has a way to improve the code it will be appreciated: **
using IRail.BLL.SAP;
using IRail.Entities.SAP.Report;
using IRail.WebAPI.Heplers;
using Logger;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Http;
using System.Web.Script.Serialization;
using System.Web.Services;
namespace IRail.WebAPI
{
public class EventInfo
{
public string QMNUM { get; set; }
public string QMART { get; set; }
public string STATUS { get; set; }
public string MAHUT_CODE { get; set; }
public string MAHUT_TXT { get; set; }
public string START_DATE { get; set; }
public string START_TIME { get; set; }
public string END_DATE { get; set; }
public string END_TIME { get; set; }
public string ZQMNUM { get; set; }
public string QMTXT { get; set; }
public string IKUN { get; set; }
public string ZLONG { get; set; }
public string LAT { get; set; }
public string TPLNR { get; set; }
public string ZZKM_NUM { get; set; }
public string ZZTOKM_NUM { get; set; }
}
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[System.ComponentModel.ToolboxItem(false)]
[System.Web.Script.Services.ScriptService]
public class Events : System.Web.Services.WebService
{
public static readonly ILogger _logger = LogManager.GetLogger();
[WebMethod]
public string UpdateEvent(EventInfo eventInfo)
{
// create an instance of SapClient object an fill it with the input parameters,
// that passes by the url to the function using the eventInfo class.
SapClient SapArgs = new SapClient()
{
params_input = "",
QNUM = eventInfo.QMNUM,
QMART = eventInfo.QMART,
STATUS = eventInfo.STATUS,
MAHUT_CODE = eventInfo.MAHUT_CODE,
MAHUT_TXT = eventInfo.MAHUT_TXT,
START_DATE = eventInfo.START_DATE,
START_TIME = eventInfo.START_TIME,
END_DATE = eventInfo.END_DATE,
END_TIME = eventInfo.END_TIME,
ZQMNUM = eventInfo.ZQMNUM,
QMTXT = eventInfo.QMTXT,
IKUN = eventInfo.IKUN,
ZLONG = eventInfo.ZLONG,
LAT = eventInfo.LAT,
TPLNR = eventInfo.TPLNR,
ZZKM_NUM = eventInfo.ZZKM_NUM,
ZZTOKM_NUM = eventInfo.ZZTOKM_NUM,
ikunx = "",
ikuny = "",
operation_type = "",
returnZ = "",
returnM = "",
returnTrueCurves = "",
f = ""
};
string errorMsg = String.Empty;
string outputJson = String.Empty;
ApiHelper apiHelper = new ApiHelper();
try
{
// create an instance of JS Serializer.
var jss = new JavaScriptSerializer();
// serialize the object to convert it to json format.
JObject sapArgs = JObject.Parse(jss.Serialize(SapArgs));
// decerialize the object back from json format to pass the JSON string representation
// of the sapArgs object as the input to the callGPAsync method.
var dict = jss.Deserialize<Dictionary<string, string>>(sapArgs.ToString());
// create an instance of EventsEngine.
EventsEngine eventsEngine = new EventsEngine();
// assign the type of the event to the events object:
// check the event type.
SapArgs.operation_type = eventsEngine.CheckEventType(dict, ref errorMsg);
// assign the event type that has returned to the sapArgs object's operation_type parameter.
sapArgs["operation_type"] = SapArgs.operation_type; // "1";// set operation_type for test;
// if encountered an error return the content of it.
if (errorMsg != "") return "UpdateEvent ERROR: " + errorMsg;
_logger.Info($"Username: {Utils.GetUserName()}, UpdateEvent : {sapArgs.ToString()}, eventType :{SapArgs.operation_type}");
if (!string.IsNullOrWhiteSpace(apiHelper.getValueFromDict(dict, "IKUN")) && dict["IKUN"].ToString() == "Y")
{
var res = apiHelper.convertCoordiateWGSToITM(sapArgs).GetAwaiter().GetResult();
}
outputJson = apiHelper.callGPAsync(sapArgs).GetAwaiter().GetResult();
try
{
// if there is result from submitted job add operation_type
outputJson = outputJson.Replace("}", ", \"operation_type\" = \"" + SapArgs.operation_type + "\" }");
}
catch (Exception outputEx)
{
return "outputJson ERROR: " + outputEx;
}
var response = new HttpResponseMessage(HttpStatusCode.OK);
response.Content = new StringContent(outputJson, System.Text.Encoding.UTF8, "application/json");
return outputJson;
}
catch (Exception ex)
{
_logger.Error(" UpdateEvent ERROR : " + SapArgs.ToString() + ", eventType :" + SapArgs.operation_type + ", errorMsg :" + errorMsg);
_logger.Error(ex);
return "UpdateEvent ERROR: update failed on exception. please check logs.";
}
//0. check with documentation - what are the parameters - in sap document
//0. log -> input call
//1. properties input validation -
// A. all inputs are correct //2.4 in documents ---> function in BLL that does the validation
//2. if all ok - -- delete prev event
//3. call GP service to update new event
//4. return success + log reult
}
}
}
I did not try anything i just want to understand the logic.

Why am I getting a null pointer error in my view model ASP.NET MVC

I am currently trying to read data from a database and send that data into a list so that I can display the data items in a list however, I am getting a null pointer error in my view near my foreach loop.
Controller:
public ActionResult Index()
{
try
{
connection.Open();
SqlCommand myCommand = new SqlCommand("SELECT Firstname, ExerciseName, PR_Weight FROM Users, Exercises, PR WHERE Exercises.ExerciseID = PR.ExerciseID AND PR.Username = Users.Username AND Firstname = 'Evan' ", connection);
SqlDataReader myReader = myCommand.ExecuteReader();
Globals.PRList.Clear();
while (myReader.Read())
{
PRViewModel pr = new PRViewModel();
pr.PR_ID = (int)myReader["PR_ID"];
pr.Username = myReader["Username"].ToString();
pr.ExerciseID = (int)myReader["ExerciseID"];
pr.PR_Weight = (int)myReader["PR_Weight"];
pr.PR_Date = myReader["PR_Date"].ToString();
pr.Exercises.exerciseID = (int)myReader["ExerciseID"];
pr.Exercises.exercsieName = myReader["ExerciseName"].ToString();
Globals.PRList.Add(pr);
}
}
catch (Exception err)
{
ViewBag.Status = 0;
}
finally
{
connection.Close();
}
return View(Globals.PRList);
}
Globals Class:
public static class Globals
{
public static string myConnection = #"Data Source=TYRONSSPEEDYBOY\SQLEXPRESS02;Initial Catalog=PR_Tracker_DB1;Integrated Security=True";
public static List<PRViewModel> PRList = new List<PRViewModel>();
}
Index View:
#foreach (PRViewModel pr in Model)
{
<tr>
<td>#pr.PR_ID</td>
<td>#pr.Username</td>
<td>#pr.ExerciseID</td>
<td>#pr.PR_Weight</td>
<td>#pr.PR_Date</td>
PRViewModel:
public PRViewModel()
{
Exercises = new ExerciseViewModel();
}
public int PR_ID { get; set; }
public string Username { get; set; }
public int ExerciseID { get; set; }
public int PR_Weight { get; set; }
public string PR_Date { get; set; }
public ExerciseViewModel Exercises { get; set; }
You select these fields from the database
SELECT Firstname, ExerciseName, PR_Weight
But you then go on to read out several values which don't exist in the reader (because they're not returned by your query)
PR_ID
Username
List item
ExerciseID
PR_Weight
PR_Date
ExerciseID
ExerciseName (only this one exists in your query)
Try correcting your query. Your code also assumes none of these fields are null in the database, if they are casting is likely to fail.

How to insert the file name in the database using Ado.Net? Instead of the file name null value is being inserted

How to insert the file name in the database using Ado.Net? Instead of the file name null value is being inserted
CONNECTION CODE-
public bool AddBooks(LibraryManagementModel LibraryObject)
{
SqlCommand cmd = new SqlCommand("AddBooks", connection);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("#book_id", LibraryObject.Id);
cmd.Parameters.AddWithValue("#book_name", LibraryObject.Book_Name);
cmd.Parameters.AddWithValue("#author", LibraryObject.Author);
cmd.Parameters.AddWithValue("#publisher", LibraryObject.Publisher);
cmd.Parameters.AddWithValue("#date_of_publication", LibraryObject.Date_of_publication);
cmd.Parameters.AddWithValue("#year", LibraryObject.Year);
cmd.Parameters.AddWithValue("#category", LibraryObject.Category);
cmd.Parameters.AddWithValue("#price", LibraryObject.Price);
cmd.Parameters.AddWithValue("#image",LibraryObject.Image);
if (connection.State == ConnectionState.Closed)
connection.Open();
int i = cmd.ExecuteNonQuery();
connection.Close();
if (i > 1)
{
return true;
}
else
{
return false;
}
}
CONTROLLER CODE-
public ActionResult AddBooks(LibraryManagementModel LibraryObject)
{
string fileName = Path.GetFileNameWithoutExtension(LibraryObject.ImageFile.FileName);
string extension = Path.GetExtension(LibraryObject.ImageFile.FileName);
fileName = fileName + DateTime.Now.ToString("yymmssfff") + extension;
LibraryObject.Image = "~/Image/" + fileName;
fileName = Path.Combine(Server.MapPath("~/Image/"), fileName);
LibraryObject.ImageFile.SaveAs(fileName);
if (ModelState.IsValid == true)
{
BooksDB.AddBooks(LibraryObject);
ModelState.Clear();
ViewBag.AddMsg = "<script>('Data Saved')</script>";
return RedirectToAction("Index");
}
else
{
ViewBag.AddMsg = "<script>('something went wrong')</script>";
return RedirectToAction("Index");
}
return View();
}
MODEL CODE-
public class LibraryManagementModel
{
public int Id { get; set; }
[Required]
public string Book_Name { get; set; }
[Required]
public string Author { get; set; }
[Required]
public string Publisher { get; set; }
[Required]
[DataType(DataType.Date)]
public string Date_of_publication { get; set; }
[Required]
public string Year { get; set; }
public string Category { get; set; }
public string Price{ get; set; }
[DisplayName("Upload Book Image")]
public string Image { get; set; }
public HttpPostedFileBase ImageFile { get; set; }
}

Why is Cosmos DB giving me an "The input name '{' is invalid" error when I call CreateItemAsync

I am working on an ASP.Net Core 3.0 API with an Azure Cosmos DB as the persistence store. This is my first attempt at working with Cosmos DB. When I try to create a new item (document), I am getting back an error in Postman that says...
"Response status code does not indicate success: 400 Substatus: 0
Reason: (Message: {\"Errors\":[\"The input name '{' is invalid.
Ensure to provide a unique non-empty string less than '1024' characters."
I cannot figure out what is causing this problem.
I am using the Microsoft.Azure.Cosmos v3.4.0 nuget in my project
Here is the method in my repository for adding the new Account document.
public async Task AddAccountAsync(Account account)
{
await _container.CreateItemAsync(account, new PartitionKey(account.Id));
}
Here is a pic of the property values when I hover over the "Account account" object while in debug mode.
My container in Cosmos DB is set up with /id as the partition key.
Here is my request body in Postman;
{
"id": "00000000-0000-0000-0000-000000000000",
"accountName": "Test Company 1",
"accountType": 1,
"ownerId": "00000000-0000-0000-0000-000000000000",
"isTaxExempt": false,
"mailJobProxyId": "00000000-0000-0000-0000-000000000000",
"salesPersonId": "00000000-0000-0000-0000-000000000000"
}
Here is the Account class;
public class Account
{
// Aggregate state properties
[JsonProperty(PropertyName = "id")]
public AccountId Id { get; set; }
[JsonProperty(PropertyName = "accountName")]
public AccountName AccountName { get; set; }
[JsonProperty(PropertyName = "accountType")]
public AccountTypes AccountType { get; set; }
[JsonProperty(PropertyName = "ownerId")]
public OwnerId OwnerId { get; set; }
[JsonProperty(PropertyName = "isTaxExempt")]
public bool IsTaxExempt { get; set; }
[JsonProperty(PropertyName = "mailJobProxyId")]
public MailJobProxyId MailJobProxyId { get; set; }
[JsonProperty(PropertyName = "salesPersonId")]
public SalesPersonId SalesPersonId { get; set; }
[JsonProperty(PropertyName = "addresses")]
public List<Address.Address> Addresses { get; set; }
[JsonProperty(PropertyName = "contacts")]
public List<Contact.Contact> Contacts { get; set; }
[JsonProperty(PropertyName = "postagePaymentMethods")]
public List<PostagePaymentMethod.PostagePaymentMethod> PostagePaymentMethods { get; set; }
public Account(string id, string accountName, AccountTypes accountType, string ownerId, Guid mailJobProxyId, Guid salesPersonId, bool isTaxExempt)
{
Id = AccountId.FromString(id);
AccountName = AccountName.FromString(accountName);
AccountType = accountType;
OwnerId = OwnerId.FromString(ownerId);
MailJobProxyId = new MailJobProxyId(mailJobProxyId);
SalesPersonId = new SalesPersonId(salesPersonId);
IsTaxExempt = isTaxExempt;
Addresses = new List<Address.Address>();
Contacts = new List<Contact.Contact>();
PostagePaymentMethods = new List<PostagePaymentMethod.PostagePaymentMethod>();
Status = Status.Active;
}
}
Please let me know if you need other code examples.
UPDATE 11/6/19 at 6:43p EST
Here is the AccountId value object
public class AccountId : Value<AccountId>
{
public string Value { get; internal set; }
// Parameterless constructor for serialization requirements
protected AccountId() { }
internal AccountId(string value) => Value = value;
// Factory pattern
public static AccountId FromString(string accountId)
{
CheckValidity(accountId);
return new AccountId(accountId);
}
public static implicit operator string(AccountId accountId) => accountId.Value;
private static void CheckValidity(string value)
{
if (!Guid.TryParse(value, out _))
{
throw new ArgumentException(nameof(value), "Account Id is not a GUID.");
}
}
}
And here is the initialization class in Startup.cs that sets up the database and container.
private static async Task<AccountsRepository> InitializeCosmosClientAccountInstanceAsync(IConfigurationSection configurationSection)
{
var databaseName = configurationSection.GetSection("DatabaseName").Value;
string uri = configurationSection.GetSection("Uri").Value;
string key = configurationSection.GetSection("Key").Value;
CosmosClientBuilder clientBuilder = new CosmosClientBuilder(uri, key);
CosmosClient client = clientBuilder
.WithConnectionModeDirect()
.Build();
DatabaseResponse database = await client.CreateDatabaseIfNotExistsAsync(databaseName);
string containerName = configurationSection.GetSection("AccountsContainerName").Value;
await database.Database.CreateContainerIfNotExistsAsync(containerName, "/id");
AccountsRepository cosmosDbService = new AccountsRepository(client, databaseName, containerName);
return cosmosDbService;
}
Here is the stack trace from when the error occurs;
stackTrace": " at Microsoft.Azure.Cosmos.ResponseMessage.EnsureSuccessStatusCode()\r\n
at Microsoft.Azure.Cosmos.CosmosResponseFactory.ToObjectInternal[T]
(ResponseMessage cosmosResponseMessage, CosmosSerializer jsonSerializer)\r\n
at Microsoft.Azure.Cosmos.CosmosResponseFactory.
<CreateItemResponseAsync>b__6_0[T](ResponseMessage cosmosResponseMessage)\r\n
at Microsoft.Azure.Cosmos.CosmosResponseFactory.ProcessMessageAsync[T]
(Task`1 cosmosResponseTask, Func`2 createResponse)\r\n at
Delivery.Api.Infrastructure.AccountsRepository.AddAccountAsync(Account
account) in
C:\\AzureDevOps\\Delivery\\Delivery.Api\\Accounts\\AccountsRepository.cs:line 20\r\n
at Delivery.Api.Accounts.AccountsApplicationService.HandleCreate(Create cmd)
in C:\\AzureDevOps\\Delivery\\Delivery.Api\\Accounts\\AccountsApplicationService.cs:line 43\r\n
at Delivery.Api.Infrastructure.RequestHandler.HandleCommand[T](T request, Func`2 handler, ILogger log)
in C:\\AzureDevOps\\Delivery\\Delivery.Api\\Infrastructure\\RequestHandler.cs:line 16
You may need to create your custom converter for your AccountId, OwnerId and so on.
Here is my test:
class AccountIdConverter
class AccountIdConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return (objectType == typeof(AccountId));
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
return AccountId.FromString(JToken.Load(reader).ToString());
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
JToken.FromObject(value.ToString()).WriteTo(writer);
}
}
class AccountId
Add toString method, and set to use custom converter
[JsonConverter(typeof(AccountIdConverter))]
public class AccountId
{
public string Value { get; internal set; }
protected AccountId() { }
internal AccountId(string value) => Value = value;
public static AccountId FromString(string accountId)
{
CheckValidity(accountId);
return new AccountId(accountId);
}
public static implicit operator string(AccountId accountId) => accountId.Value;
public override string ToString()
{
return Value;
}
private static void CheckValidity(string value)
{
if (!Guid.TryParse(value, out _))
{
throw new ArgumentException(nameof(value), "Account Id is not a GUID.");
}
}
}
class Account
class Account
{
[JsonProperty(PropertyName = "id")]
public AccountId Id { get; set; }
public Account(string id)
{
Id = AccountId.FromString(id);
}
}
Test
static void Main(string[] args)
{
// Test toString
AccountId accountId = AccountId.FromString(Guid.NewGuid().ToString());
Console.WriteLine(accountId.ToString());
// Test AccountIdConverter
Console.WriteLine(JsonConvert.SerializeObject(accountId));
// Test for serializing Account
Account account = new Account(Guid.NewGuid().ToString());
string accountJson = JsonConvert.SerializeObject(account);
Console.WriteLine(accountJson);
// Test for deserializing Account
Account accountDeserialized = JsonConvert.DeserializeObject<Account>(accountJson);
Console.WriteLine(accountDeserialized.Id);
Console.ReadLine();
}
Result
You can see that the Account object which contains an AccountId object can be serialized and deserialized correctly as expected.

The ViewData item that has the key 'distic_id' is of type 'System.Int32' but must be of type 'IEnumerable<SelectListItem>'

In my MVC project when run and I press edit option in in view at that time this error occur
The ViewData item that has the key 'distic_id' is of type 'System.Int32' but must be of type 'IEnumerable<SelectListItem>'
In my view code
#Html.DropDownListFor(m => m.distic_id, Model.disticlist)
model is
public class city
{
public List<SelectListItem> disticlist { get; set; }
public int city_id { get; set; }
[Required]
[Display(Name = "enter the District name")]
public string city_name { get; set; }
[Required]
[Display(Name = "select district ")]
public int distic_id { get; set; }
}
if you want to get city or dist list in a drop down list please see the following code
1) Remove your code
2) Create one Model like this
3) if this drop down is used in more than one page CREATE ONE CONTROLLER like CommanController
4) write one method in this controller
See Below code
First need to create Model like this
public class Industry
{
public string Id { get; set; }
public string industryName { get; set; }
public string regexindustry { get; set; }
}
public class IndustryModel
{
public SelectList industryList { get; set; }
}
In Controller
Two Step 1 is Create one method it return type is List
and Call this method in any ActionReslut with the use of object
ViewBag.list=obj.getIndustryList();
public List<Industry> getIndustryList()
{
List<Industry> objindustry = new List<Industry>();
var connString = new SqlConnection(ConfigurationManager.ConnectionStrings["connectionString"].ConnectionString);
SqlCommand sqlComm = new SqlCommand("sp_selIndustryMaster", connString);
connString.Open();
sqlComm.CommandType = CommandType.StoredProcedure;
SqlDataReader sqldr = sqlComm.ExecuteReader();
int count = 0;
while (sqldr.Read())
{
if (count == 0)
{
objindustry.Add(new Industry { Id ="", industryName = "Select Industry" });
count++;
}
else
{
objindustry.Add(new Industry { Id = Convert.ToString(sqldr["industryCode"]), industryName = sqldr["subindustry"].ToString() });
}
}
return objindustry;
}
IN VIEW
#Html.DropDownListFor(model => model.txtindustry, new SelectList(ViewBag.List, "Id", "industryName", 0))
please use it your problem may be solve,