TranscationScope with multiple database calls - c#

My scenario is to send invoice details (in PDF format) to customer's emailId on paynow button click event.
I have tried the following but getting exception after calling
actionPDF.BuildPdf(ControllerContext)
Exception is
Timeout expired. The timeout period elapsed prior to completion of the operation or the server is not responding
Code:
dbDetails _db = new dbDetails();
[HttpPost]
public JsonResult Add(Model mdl)
{
using (TransactionScope _ts = new TransactionScope())
{
//Insertion logic of invoice goes here
...
...
int i = _db.SaveChanges();
// if successfull insertion
if(i > 0)
{
var actionPDF = new Rotativa.ActionAsPdf("GetPdfReceipt", new { RegId = _receiptDetails.StudentRegistrationID.Value })
{
FileName = "Receipt.pdf"
};
// Dynamic student receipt pdf
***Getting exception here****
var byteArrayDynamic = actionPDF.BuildPdf(ControllerContext);
// Mail sending logic
......
......
_ts.Complete();
}
}
}
public ActionResult GetPdfReceipt(int RegId)
{
Common _cmn = new Common();
var _studentRegistration = _db.StudentRegistrations
.AsEnumerable()
.Where(r => r.Id == RegId)
.FirstOrDefault();
var _mdlReceiptPdf = new ReceiptPdfVM
{
CentreCode = _studentRegistration.StudentWalkInn.CenterCode.CentreCode,
CompanyAddress = _studentRegistration.StudentWalkInn.CenterCode.Address,
CompanyPhoneNo = _studentRegistration.StudentWalkInn.CenterCode.PhoneNo,
CourseFee = _studentRegistration.TotalCourseFee.Value,
CourseTitle = string.Join(",", _studentRegistration.StudentRegistrationCourses
.Select(rc => rc.MultiCourse.CourseSubTitle.Name)),
CROName = _studentRegistration.StudentWalkInn.CROCount == (int)EnumClass.CROCount.ONE ? _studentRegistration.StudentWalkInn.Employee1.Name :
_studentRegistration.StudentWalkInn.Employee1.Name + ',' + _studentRegistration.StudentWalkInn.Employee2.Name,
Duration = _studentRegistration.TotalDuration.Value,
ReceiptDate = _studentRegistration.StudentReceipts.Last(sr => sr.Status == true).DueDate.Value.ToString("dd/MM/yyyy"),
ReceiptNo = _studentRegistration.StudentReceipts.Last(sr => sr.Status == true).ReceiptNo,
RegistrationNumber = _studentRegistration.RegistrationNumber,
ServiceTax = _studentRegistration.TotalSTAmount.Value,
StudentMaskedEmailId = _cmn.MaskString(_studentRegistration.StudentWalkInn.EmailId, "email"),
StudentMaskedMobileNo = _cmn.MaskString(_studentRegistration.StudentWalkInn.MobileNo, "mobile"),
StudentName = _studentRegistration.StudentWalkInn.CandidateName,
ServiceTaxRegistrationNo = _studentRegistration.StudentWalkInn.CenterCode.STRegNo,
TotalAmount = _studentRegistration.TotalAmount.Value,
TotalAmountInWords = _cmn.NumbersToWords(_studentRegistration.TotalAmount.Value).ToUpper(),
TotalCourseFeePaid = _studentRegistration.StudentReceipts
.Where(r => r.Status == true)
.Sum(r => r.Fee.Value),
ManagerName = _cmn.GetManager(_studentRegistration.StudentWalkInn.CenterCodeId.Value)
.Name,
ReceiptDetailsList = _db.StudentReceipts
.AsEnumerable()
.Where(rc => rc.StudentRegistrationID == RegId)
.Select(rc => new ReceiptPdfVM.ReceiptDetails
{
CourseFee = rc.Fee.Value,
DatePaid = rc.DueDate.Value.ToString("dd/MM/yyyy"),
ReceiptNo = rc.ReceiptNo
}).ToList()
}
return View("Receipts", _mdlReceiptPdf);
}
protected override void Dispose(bool disposing)
{
_db.Dispose();
base.Dispose(disposing);
}
How to solve this issue? Any help will be highly appreciated.

I think the problem is that while generating the PDF document your pending database transaction times out. Move the _ts.Complete to before you generate the PDF.
dbDetails _db = new dbDetails();
[HttpPost]
public JsonResult Add(Model mdl)
{
using (TransactionScope _ts = new TransactionScope())
{
//Insertion logic of invoice goes here
...
...
int i= _db.SaveChanges();
//if successfull insertion
if(i>0)
{
_ts.Complete();
var actionPDF = new Rotativa.ActionAsPdf("GetPdfReceipt", new { RegId = _receiptDetails.StudentRegistrationID.Value })
{
FileName = "Receipt.pdf"
};
//Dynamic student receipt pdf
***Getting exception here****
var byteArrayDynamic = actionPDF.BuildPdf(ControllerContext);
//Mail sending logic
......
......
}
}
}

Related

How do I refactor the code which contains foreach loop

I need to refactor the below code so that the deleted_at logic will be outside of the foreach (var app in data) loop. I tried to create the list guids and then add guids to it but its not working because model.resources is inside the loop and it is still deleting all the apps.
I need deleted_at logic outside because I'm trying to delete all apps which are in the database but are not in new data that I'm receiving from API.
If you have a better approach on my code I would love to see that, Thank you.
public async Task GetBuilds()
{
var data = new List<GetBuildTempClass>();
var guids = new List<GetBuildTempClass>();
using (var scope = _scopeFactory.CreateScope())
{
var _DBcontext = scope.ServiceProvider.GetRequiredService<PCFStatusContexts>();
foreach (var app in data)
{
var request = new HttpRequestMessage(HttpMethod.Get,
"apps/" + app.AppGuid + "/builds?per_page=200&order_by=updated_at");
var response = await _client_SB.SendAsync(request);
var json = await response.Content.ReadAsStringAsync();
BuildsClass.BuildsRootObject model =
JsonConvert.DeserializeObject<BuildsClass.BuildsRootObject>(json);
foreach (var item in model.resources)
{
var x = _DBcontext.Builds.FirstOrDefault(o =>
o.Guid == Guid.Parse(item.guid));
if (x == null)
{
_DBcontext.Builds.Add(new Builds
{
Guid = Guid.Parse(item.guid),
State = item.state,
CreatedAt = item.created_at,
UpdatedAt = item.updated_at,
Error = item.error,
CreatedByGuid = Guid.Parse(item.created_by.guid),
CreatedByName = item.created_by.name,
CreatedByEmail = item.created_by.email,
AppGuid = app.AppGuid,
AppName = app.AppName,
Foundation = 2,
Timestamp = DateTime.Now
});
}
else if (x.UpdatedAt != item.updated_at)
{
x.State = item.state;
x.UpdatedAt = item.updated_at;
x.Timestamp = DateTime.Now;
}
var sqlresult = new GetBuildTempClass
{
AppGuid = Guid.Parse(item.guid)
};
guids.Add(sqlresult);
}
//var guids = model.resources.Select(r => Guid.Parse(r.guid));
var builds = _DBcontext.Builds.Where(o =>
guids.Contains(o.Guid) == false &&
o.Foundation == 2 && o.DeletedAt == null);
foreach (var build_item in builds)
{
build_item.DeletedAt = DateTime.Now;
}
}
await _DBcontext.SaveChangesAsync();
}
}
I got it working I added var guids = new List < Guid > (); list to store data,
added guids.Add(Guid.Parse(item.guid)); to populate the list and finally wrote var builds = _DBcontext.Builds.Where(o = >guids.Contains(o.Guid) == false && o.Foundation == 2 && o.DeletedAt == null); outside the loop.
If anyone has a better suggestion please add a new answer.
public async Task GetBuilds() {
var data = new List < GetBuildTempClass > ();
var guids = new List < Guid > ();
using(var scope = _scopeFactory.CreateScope()) {
var _DBcontext = scope.ServiceProvider.GetRequiredService < PCFStatusContexts > ();
foreach(var app in data) {
var request = new HttpRequestMessage(HttpMethod.Get, "apps/" + app.AppGuid + "/builds?per_page=200&order_by=updated_at");
var response = await _client_SB.SendAsync(request);
var json = await response.Content.ReadAsStringAsync();
BuildsClass.BuildsRootObject model = JsonConvert.DeserializeObject < BuildsClass.BuildsRootObject > (json);
foreach(var item in model.resources) {
var x = _DBcontext.Builds.FirstOrDefault(o = >o.Guid == Guid.Parse(item.guid));
if (x == null) {
_DBcontext.Builds.Add(new Builds {
Guid = Guid.Parse(item.guid),
State = item.state,
CreatedAt = item.created_at,
UpdatedAt = item.updated_at,
Error = item.error,
CreatedByGuid = Guid.Parse(item.created_by.guid),
CreatedByName = item.created_by.name,
CreatedByEmail = item.created_by.email,
AppGuid = app.AppGuid,
AppName = app.AppName,
Foundation = 2,
Timestamp = DateTime.Now
});
}
else if (x.UpdatedAt != item.updated_at) {
x.State = item.state;
x.UpdatedAt = item.updated_at;
x.Timestamp = DateTime.Now;
}
guids.Add(Guid.Parse(item.guid));
}
}
var builds = _DBcontext.Builds.Where(o = >guids.Contains(o.Guid) == false && o.Foundation == 2 && o.DeletedAt == null);
foreach(var build_item in builds) {
build_item.DeletedAt = DateTime.Now;
}
await _DBcontext.SaveChangesAsync();
}
}

Load Windows form after complete combobox data load in c#

I have a form for employees called frmEmployees where I need to load couple of combo box with data like country, category, nationality, such others.
Now when user click on to open frmEmployees, window is stuck for bit and then open. I assume that this is because of data loading and initializing the combo box.
Now! what I want is, just after click on button to open frmEmployees run a progress bar till data loading complete and then open form.
public frmEmployee()
{
InitializeComponent();
con = new Connection();
LoadComboboxDS();
}
I have tried also
private void FrmEmployee_Load(object sender, EventArgs e)
{
LoadComboboxDS();
}
private void LoadComboboxDS()
{
//company
var _companies = con.Companies.Where(x => x.IsDeleted == false).ToList();
_companies.Insert(0,new data.Models.CompanyModels.Company { Address = new data.Models.Address(), Code = null, Name = "--Select--", BaseCurrency = new data.Models.Currency() });
cbCompany.DataSource = _companies;
cbCompany.DisplayMember = "Name";
cbCompany.ValueMember = "ID";
//gender
cbGender.DataSource = Enum.GetValues(typeof(Gender));
//merital status
cbMeritalStatus.DataSource = Enum.GetValues(typeof(MaritalStatus));
//citizenship
var _citizenships = con.Countries.Select(x => x.Citizenship).Distinct().ToList();
_citizenships.Insert(0, "--Select--");
cbCitizenship.DataSource = _citizenships;
cbCitizenship.DisplayMember = "Citizenship";
//nationality
var _nations = con.Countries.Select(x => x.Name).Distinct().ToList();
_nations.Insert(0, "--Select--");
cbNationality.DataSource = _nations;
cbNationality.DisplayMember = "Name";
//domicile
var _domiciles = con.Countries.Select(x => x.Name).Distinct().ToList();
_domiciles.Insert(0, "--Select--");
cbDomicile.DataSource = _domiciles;
cbDomicile.DisplayMember = "Name";
//cast category
var _casts = con.CastCategories.Select(x => new {x.ShortText, x.Description}).Distinct().ToList();
_casts.Insert(0, new { ShortText = "", Description = "--Select--" });
cbCategory.DataSource = _casts;
cbCategory.DisplayMember = "Description";
cbCategory.ValueMember = "ShortText";
//religion
cbReligion.DataSource = Enum.GetValues(typeof(Religion));
}
You can use Async extension methods of Entity Framework 6 to make your code asynchronous.
Separate your data access and presentation layer, at first:
public static class MyRepository // consider not static, just an example
{
public static async Task<List<Company>> GetCompanies()
{
using (var connection = new Connection()) // consider factory
{
return await con.Companies.Where(x => x.IsDeleted == false).ToListAsync();
}
}
public async Task<List<Citizenship>> GetCitizenships()
{
using (var connection = new Connection()) // factory?
{
return await con.Countries.Select(x => x.Citizenship).Distinct().ToList();
}
}
}
Then, you can run all these tasks at once and wait for them to complete:
// Wherever you are going to open frmEmployee
public async Task openFrmEmployee_OnClick(object sender, EventArgs e)
{
var getCompaniesTask = MyRepository.GetCompanies();
var getCitizenshipsTask = MyRepository.GetCitizenships();
await Task.WhenAll(getCompaniesTask, getCitizenshipsTask); // UI thread is not blocked
var form = new FrmEmployee(getCompaniesTask.Result, getCitizenshipsTask.Result); // form is created with data
}
Now, you only need to make your form accept complete data in constructor instead of making your form load this data which breaks abstraction:
public class FrmEmployees
{
public FrmEmployees(List<Company> companies, List<Citizenship> citizenships)
{
companies.Insert(0,new data.Models.CompanyModels.Company { Address = new data.Models.Address(), Code = null, Name = "--Select--", BaseCurrency = new data.Models.Currency() });
cbCompany.DataSource = companies;
cbCompany.DisplayMember = "Name";
cbCompany.ValueMember = "ID";
citizenships.Insert(0, "--Select--");
cbCitizenship.DataSource = _citizenships;
cbCitizenship.DisplayMember = "Citizenship";
// etc.
}
}
One important thing: you can get many tasks and many data passed to a form constructor. If all this data is going to be used often togetther, then you would probably want to encapsulate this "get all these things" logic into a single place to remove possible code duplication.
See what I have done... if anyone can review my code it would be appreciable.
public class EmployeeFormDataRepesenter
{
public List<Company> Companies { get; set; }
public List<Country> Countries { get; set; }
public List<CastCategory> CastCategories { get; set; }
}
public void LoadData(EmployeeFormDataRepesenter representer)
{
//gender
cbGender.DataSource = Enum.GetValues(typeof(Gender));
//merital status
cbMeritalStatus.DataSource = Enum.GetValues(typeof(MaritalStatus));
//religion
cbReligion.DataSource = Enum.GetValues(typeof(Religion));
//company
var _companies = representer.Companies;
_companies.Insert(0, new data.Models.CompanyModels.Company { Address = new data.Models.Address(), Code = null, Name = "--Select--", BaseCurrency = new data.Models.Currency() });
cbCompany.DataSource = _companies;
cbCompany.DisplayMember = "Name";
cbCompany.ValueMember = "ID";
//citizenship
var _citizenships = representer.Countries.Select(x => x.Citizenship).ToList();
_citizenships.Insert(0, "--Select--");
cbCitizenship.DataSource = _citizenships;
cbCitizenship.DisplayMember = "Citizenship";
//nationality
var _nations = representer.Countries.Select(x => x.Name).ToList();
_nations.Insert(0, "--Select--");
cbNationality.DataSource = _nations;
cbNationality.DisplayMember = "Name";
//domicile
var _domiciles = representer.Countries.Select(x => x.Name).ToList();
_domiciles.Insert(0, "--Select--");
cbDomicile.DataSource = _domiciles;
cbDomicile.DisplayMember = "Name";
//cast category
var _casts = representer.CastCategories.Select(x => new { x.ShortText, x.Description }).Distinct().ToList();
_casts.Insert(0, new { ShortText = "", Description = "--Select--" });
cbCategory.DataSource = _casts;
cbCategory.DisplayMember = "Description";
cbCategory.ValueMember = "ShortText";
}
private async void btnEmplyee_Click(object sender, EventArgs e)
{
con = new Connection();
Action showProgress = () => frmStatrup._progressBar.Visible = true;
Action hideProgress = () => frmStatrup._progressBar.Visible = false;
EmployeeFormDataRepesenter representer;
Task<List<Company>> _taskCompany = new Task<List<Company>>(() =>
{
BeginInvoke(showProgress);
var list = con.Companies.ToListAsync();
BeginInvoke(hideProgress);
if (list != null)
return list.Result;
return null;
});
Task<List<Country>> _taskCountry = new Task<List<Country>>(() =>
{
BeginInvoke(showProgress);
var list = con.Countries.ToListAsync();
BeginInvoke(hideProgress);
if (list != null)
return list.Result;
return null;
});
Task<List<CastCategory>> _taskCasts = new Task<List<CastCategory>>(() =>
{
BeginInvoke(showProgress);
var list = con.CastCategories.ToListAsync();
BeginInvoke(hideProgress);
if (list != null)
return list.Result;
return null;
});
_taskCompany.Start();
var _companies = await _taskCompany;
_taskCountry.Start();
var _countries = await _taskCountry;
_taskCasts.Start();
var _casts = await _taskCasts;
if (_companies.Count != 0)
{
representer = new EmployeeFormDataRepesenter();
representer.Companies = _companies;
representer.Countries = _countries;
representer.CastCategories = _casts;
}
else
{
representer = null;
}
if (representer != null)
{
frmEmployee _emp = new frmEmployee();
_emp.LoadData(representer);
Functions.OpenForm(_emp, this.ParentForm);
}
}

How to fetch the data from SqLite database

I have created database in SqLite in my windows app, now I want to fetch the data from my database. This is the code how I inserted the data in databse.
var dbpath = Path.Combine(Windows.Storage.ApplicationData.Current.LocalFolder.Path, "scrapbook.sqlite");
using (var db = new SQLite.SQLiteConnection(dbpath))
{
// Create the tables if they don't exist
var bg = listAlbumContainer[0] as AlbumContainer;
var albumbg = bg.BackgroundImageName;
var sk = listAlbumContainer[0].listAlbumContainer;
var _audio = listAlbumContainer[0].listAlbumContainer5;
var _video = listAlbumContainer[0].listAlbumContainer3;
var wa = listAlbumContainer[0].listAlbumContainer4;
var ci = listAlbumContainer[0].listAlbumContainer2;
var gi = listAlbumContainer[0].listAlbumContainer1;
string snodesticker = Serializeanddeserializwhelper.Serialize(sk);
string nodegi = Serializeanddeserializwhelper.Serialize(gi);
string nodeci = Serializeanddeserializwhelper.Serialize(ci);
string nodewa = Serializeanddeserializwhelper.Serialize(wa);
string nodevideo = Serializeanddeserializwhelper.Serialize(_video);
string nodeaudio = Serializeanddeserializwhelper.Serialize(_audio);
var TittledataInsertCheck = db.Table<Title>().Where(x => x.ALBUM_TITLE.Contains(nametxt.Text)).FirstOrDefault();
if (TittledataInsertCheck == null)
{
db.Insert(new Title()
{
ALBUM_TITLE = nametxt.Text
});
var TittledataInsert = db.Table<Title>().Where(x => x.ALBUM_TITLE.Contains(nametxt.Text)).FirstOrDefault();
if (TittledataInsert != null)
{
db.Insert(new PAGE()
{
PAGE_BACKGROUND = albumbg,
TITLE_ID = TittledataInsert.ID
});
}
}
else
{
await new MessageDialog("Tittle Already Found Please change tittle").ShowAsync();
return;
}
var PagedataInsert = db.Table<PAGE>().Where(x => x.PAGE_BACKGROUND.Contains(albumbg)).FirstOrDefault();
if (PagedataInsert != null)
{
db.Insert(new CONTENT
{
PAGE_ID = PagedataInsert.ID,
STICKERS = snodesticker,
AUDIO = nodeaudio,
VIDEO = nodevideo,
GALLERY_IMAGES = nodegi,
CAMERA_IMAGES = nodeci,
WOARD_ART = nodewa
});
}
db.Commit();
db.Dispose();
db.Close();
var line = new MessageDialog("Records Inserted");
await line.ShowAsync();
}
Is this the right way to insert the data?
I have a canvas on which I set the background image. And on this background some images, video and audio.

Error on SaveChanges When Using UnityContainer

I have an Asp.Net MVC 5 using Entity Framework 6. I am using Unity.MVC5 Version 1.2.3.0
The issue I am having is that I would get the following error on certain scenarios when saving to the database
Additional information: The operation failed: The relationship could
not be changed because one or more of the foreign-key properties is
non-nullable. When a change is made to a relationship, the related
foreign-key property is set to a null value. If the foreign-key does
not support null values, a new relationship must be defined, the
foreign-key property must be assigned another non-null value, or the
unrelated object must be deleted.
After troubleshooting the issue I believe it has to do with how I have Unity.MVC5 configured. Here is my Unity.Config.cs
public static class UnityConfig
{
public static void RegisterComponents()
{
var container = new UnityContainer();
// register all your components with the container here
// it is NOT necessary to register your controllers
// e.g. container.RegisterType<ITestService, TestService>();
container.RegisterTypes(AllClasses.FromLoadedAssemblies(), WithMappings.FromMatchingInterface, WithName.Default);
container.RegisterType<IUnitOfWork, UnitOfWork>(new InjectionConstructor(new MasterContext()));
DependencyResolver.SetResolver(new UnityDependencyResolver(container));
}
}
So my controller would have something like this
private IService _Service;
MyController(IService service)
{
_Service = service;
}
However it looks like the data is not refreshing, Although when I use a SQL Profiler , it shows as it is making a call but the data is not refreshed as I do a breakpoint it still has old data. If I do away with the Unity.MVC injecting the classes, then the data gets refreshed and savechanges works fine.
I am overwriting the EF Context SaveChanges , here is the code
public override int SaveChanges()
{
var autoDetectChanges = Configuration.AutoDetectChangesEnabled;
try
{
Configuration.AutoDetectChangesEnabled = false;
ChangeTracker.DetectChanges();
var errors = GetValidationErrors().ToList();
if (errors.Any())
{
throw new DbEntityValidationException("Validation errors found during save.", errors);
}
//For modified column
var changedInfo = ChangeTracker.Entries().Where(t => t.State == EntityState.Modified)
.Select(t => new
{
Original = t.OriginalValues.PropertyNames.ToDictionary(pn => pn, pn => t.OriginalValues[pn]),
Current = t.CurrentValues.PropertyNames.ToDictionary(pn => pn, pn => t.CurrentValues[pn]),
objectContext = ((IObjectContextAdapter)this).ObjectContext,
ent = t,
});
foreach (var item in changedInfo)
{
if (GetTableInformation.GetTableName(item.objectContext, item.ent) != "HistoryLogs")
{
var result = GetDifference.GetChangedValues(item.Original, item.Current, item.objectContext, item.ent);
HistoryLog history = new HistoryLog();
history.Description = result[0];
history.TableFields = result[1];
history.UserId = userId;
history.TableAction = "Modified";
history.PrimaryKeyValue = Convert.ToInt32(result[2]);
history.TableName = result[3];
if (history.TableName == "MainRates")
{
MainRate rate = MainRates.SingleOrDefault(r => r.RateId == history.PrimaryKeyValue);
history.InstitutionId = rate.InstitutionId;
}
else if (history.TableName == "ProgramRates")
{
ProgramRate rate = ProgramRates.SingleOrDefault(r => r.RateId == history.PrimaryKeyValue);
history.InstitutionId = rate.InstitutionId;
}
else
{
int institutiondId;
if (int.TryParse(result[4], out institutiondId))
{
history.InstitutionId = institutiondId;
}
else
{
history.InstitutionId = null;
}
}
//InstitutionName and OPEID are being updated by trigger(executer after each insert operations)
//Check if there is any modified column or not
if (!string.IsNullOrEmpty(history.TableFields))
HistoryLogs.Add(history);
}
}
//For Deleted columns
var deletedInfo = ChangeTracker.Entries().Where(t => t.State == EntityState.Deleted)
.Select(t => new
{
Original = t.OriginalValues.PropertyNames.ToDictionary(pn => pn, pn => t.OriginalValues[pn]),
objectContext = ((IObjectContextAdapter)this).ObjectContext,
ent = t,
});
foreach (var item in deletedInfo)
{
if (GetTableInformation.GetTableName(item.objectContext, item.ent) != "HistoryLogs")
{
var result = GetDifference.GetDeletedValues(item.Original, item.objectContext, item.ent);
HistoryLog history = new HistoryLog();
history.Description = result[0];
history.TableFields = result[1];
history.UserId = userId;
history.TableAction = "Deleted";
history.PrimaryKeyValue = Convert.ToInt32(result[2]);
history.TableName = result[3];
if (history.TableName == "MainRates")
{
int locationRateId = (int)item.Original["LocationRateId"];
history.InstitutionId = LocationRates.SingleOrDefault(l => l.Id == locationRateId).InstitutionId;
}
else if (history.TableName == "ProgramRates")
{
ProgramRate rate = ProgramRates.SingleOrDefault(r => r.RateId == history.PrimaryKeyValue);
history.InstitutionId = rate.InstitutionId;
}
else
{
history.InstitutionId = result[4] == null ? null : (int?)int.Parse(result[4]);
}
//InstitutionName and OPEID are being updated by trigger(executer after each insert operations)
history.InstitutionName = "";
history.OpeidNumber = "";
//Check if there is any modified column or not
if (!string.IsNullOrEmpty(history.TableFields))
HistoryLogs.Add(history);
}
}
// For data that is added
string[] applicableTables = new string[] { "EligiblePrograms", "Fees", "LocationRates", "MainRates", "ProgramRates" };
var addedInfo = ChangeTracker.Entries().Where(t => t.State == EntityState.Added)
.Select(t => new
{
Current = t.CurrentValues.PropertyNames.ToDictionary(pn => pn, pn => t.CurrentValues[pn]),
ObjectContext = ((IObjectContextAdapter)this).ObjectContext,
Entity = t,
}).ToList();
//Placing this here adds the primary keys to the new values before saving their history.
Configuration.ValidateOnSaveEnabled = false;
int rVal = base.SaveChanges();
foreach (var item in addedInfo)
{
string tableName = GetTableInformation.GetTableName(item.ObjectContext, item.Entity);
if (applicableTables.Contains(tableName))
{
var result = GetDifference.GetDeletedValues(item.Current, item.ObjectContext, item.Entity);
HistoryLog history = new HistoryLog();
history.Description = result[0];
history.TableFields = result[1];
history.UserId = userId;
history.TableAction = "Added";
history.PrimaryKeyValue = Convert.ToInt32(result[2]);
history.TableName = result[3];
if (history.TableName == "MainRates")
{
history.InstitutionId = ((MainRate)item.Entity.Entity).InstitutionId;
}
else if (history.TableName == "ProgramRates")
{
history.InstitutionId = ((ProgramRate)item.Entity.Entity).InstitutionId;
}
else
{
history.InstitutionId = result[4] == null ? null : (int?)int.Parse(result[4]);
}
history.InstitutionName = "";
history.OpeidNumber = "";
//Check if there is any modified column or not
if (!string.IsNullOrEmpty(history.TableFields))
HistoryLogs.Add(history);
}
}
rVal += base.SaveChanges();
return rVal;
}
finally
{
Configuration.AutoDetectChangesEnabled = autoDetectChanges;
}
}
Then my Service class will do something like this:
Header header = _uow.MyRepository.GetByHeaderId(model.Id, model.HeaderId);
header.WebAddresses = string.Join(",", model.WebAddresses.ToArray());
header.Date = DateTime.Parse(model.Date);
header.IsField1 = model.Field1;
header.Field2 = model.Field2;
header.Field3 = model.Field3;
_uow.SaveChanges();

SOAP .net web service: Server did not recognize the value of HTTP Header SOAPAction

When i try to call my webservice do i get the following error:
System.Web.Services.Protocols.SoapException: Server did not recognize the value of HTTP Header SOAPAction: http://tempuri.org/GetFlights. at System.Web.Services.Protocols.Soap11ServerProtocolHelper.RouteRequest() at System.Web.Services.Protocols.SoapServerProtocol.RouteRequest(SoapServerMessage message) at System.Web.Services.Protocols.SoapServerProtocol.Initialize() at System.Web.Services.Protocols.ServerProtocolFactory.Create(Type type, HttpContext context, HttpRequest request, HttpResponse response, Boolean& abortProcessing)
http://sogaardlameduck.azurewebsites.net/LameDuckService.asmx?WSDL
When we use the webservice in other .net programs do we not have any problems, but all Java applicaitons fail with this error. What we we missing to support SOAPAction?
This is our web service:
[WebService(Namespace = "http://sogaardlameduck.azurewebsites.net/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[System.ComponentModel.ToolboxItem(false)]
// To allow this Web Service to be called from script, using ASP.NET AJAX, uncomment the following line.
// [System.Web.Script.Services.ScriptService]
public class LameDuckService : System.Web.Services.WebService
{
private TravelGoodEntities entities;
private BankService bankService;
private int groupNumber;
private accountType account;
public LameDuckService()
{
entities = new TravelGoodEntities();
bankService = new BankService();
groupNumber = 10;
account = new accountType()
{
number = "50208812",
name = "LameDuck"
};
}
[WebMethod(Description = "Book a flight")]
public int BookFlight(int bookingId, CreditCardModel model)
{
var flight = entities.Flights.Where(x => x.Id == bookingId).FirstOrDefault();
if (flight == null)
throw new FlightNotFoundException();
// count reservations
var count = flight.Flight_Reservations.Count;
if(count >= flight.Seats)
throw new NoAvailableSeatsException();
try
{
if (!bankService.validateCreditCard(groupNumber, new creditCardInfoType()
{
name = model.Name,
number = model.Number,
expirationDate = new expirationDateType()
{
year = model.ExpirationDateYear,
month = model.ExpirationDateMonth
}
}, flight.Price))
throw new CreditCardValidationFailedException();
if (!bankService.chargeCreditCard(groupNumber, new creditCardInfoType()
{
name = model.Name,
number = model.Number,
expirationDate = new expirationDateType()
{
year = model.ExpirationDateYear,
month = model.ExpirationDateMonth
}
}, flight.Price, account))
throw new CreditCardChargeFailedException();
}
catch (SoapException e)
{
throw new CreditCardValidationFailedException();
}
var reservation = new DataAccess.Flight_Reservations()
{
FlightId = flight.Id,
Booked = DateTime.UtcNow
};
entities.Flight_Reservations.Add(reservation);
entities.SaveChanges();
return reservation.Id;
}
[WebMethod(Description = "Search for flights")]
public List<Models.Flight> GetFlights(FlightSearchModel model)
{
var select = entities.Flights.Select(x => x);
if (model.DestinationLocation != null)
select = select.Where(x => x.DestinationLocation == model.DestinationLocation);
if (model.DepartureLocation != null)
select = select.Where(x => x.DepartureLocation == model.DepartureLocation);
if (model.Date != new DateTime())
select = select.Where(x => x.DepartueTime.Year == model.Date.Year &&
x.DepartueTime.Month == model.Date.Month &&
x.DepartueTime.Day == model.Date.Day);
return select.Select(x => new Models.Flight()
{
Id = x.Id,
Airline = x.Airline,
ArrivalTime = x.ArrivalTime,
Carrier = x.Carrier,
DepartueTime = x.DepartueTime,
DepartureLocation = x.DepartureLocation,
DestinationLocation = x.DestinationLocation,
Price = x.Price,
Seats = x.Seats
}).ToList();
}
[WebMethod(Description = "Cancel a flight")]
public bool CancelFlight(int bookingId, CreditCardModel model)
{
var booking = entities.Flight_Reservations.Where(x => x.Id == bookingId).FirstOrDefault();
if (booking == null)
throw new FlightNotFoundException();
var flight = entities.Flights.Where(x => x.Id == booking.FlightId).FirstOrDefault();
if (flight == null)
throw new FlightNotFoundException();
if (!bankService.refundCreditCard(groupNumber, new creditCardInfoType()
{
name = model.Name,
number = model.Number,
expirationDate = new expirationDateType()
{
year = model.ExpirationDateYear,
month = model.ExpirationDateMonth
}
}, flight.Price, account))
throw new UnableToRefundException();
entities.Flight_Reservations.Remove(booking);
entities.SaveChanges();
return true;
}
[WebMethod(Description = "Get a flight by booked id")]
public Models.Flight GetFlightByBookedId(int bookingId)
{
var booking = entities.Flight_Reservations.Where(c => c.Id == bookingId).FirstOrDefault();
if (booking == null)
throw new FlightNotFoundException();
var x = entities.Flights.Where(c => c.Id == booking.FlightId).FirstOrDefault();
if (x == null)
throw new FlightNotFoundException();
return new Models.Flight()
{
Id = x.Id,
Airline = x.Airline,
ArrivalTime = x.ArrivalTime,
Carrier = x.Carrier,
DepartueTime = x.DepartueTime,
DepartureLocation = x.DepartureLocation,
DestinationLocation = x.DestinationLocation,
Price = x.Price,
Seats = x.Seats
};
}
[WebMethod(Description = "Get a flight by id")]
public Models.Flight GetFlight(int id)
{
var x = entities.Flights.Where(c => c.Id == id).FirstOrDefault();
if (x == null)
throw new FlightNotFoundException();
return new Models.Flight()
{
Id = x.Id,
Airline = x.Airline,
ArrivalTime = x.ArrivalTime,
Carrier = x.Carrier,
DepartueTime = x.DepartueTime,
DepartureLocation = x.DepartureLocation,
DestinationLocation = x.DestinationLocation,
Price = x.Price,
Seats = x.Seats
};
}
}
Update:
I get the show error on: http://wsdlbrowser.com/soapclient?wsdl_url=http%3A%2F%2Fsogaardlameduck.azurewebsites.net%2FLameDuckService.asmx%3FWSDL&function_name=GetFlights
But if i use: http://www.soapclient.com/ Do i not have any problems:

Categories