partial void OnValidate(ChangeAction action) {
if (!IsValid)
throw new ApplicationException("Rule violations prevent saving");
}
i am following this tutorial:
http://aspnetmvcbook.s3.amazonaws.com/aspnetmvc-nerdinner_v1.pdf
and am not able to compile the above code. it is in my NerdDinner.Models.Dinner
am i placing it in the wrong location?
here's the class:
public partial class Dinner {
public bool IsValid {
get { return (GetRuleViolations().Count() == 0); }
}
public IEnumerable<RuleViolation> GetRuleViolations() {
yield break;
}
partial void OnValidate(ChangeAction action) {
if (!IsValid)
throw new ApplicationException("Rule violations prevent saving");
}
}
here's the error im getting
Error 1 The type or namespace name 'ChangeAction' could not be found (are you missing a using directive or an assembly reference?)
please excuse the beginner's question and please let me know if you need any other details. im almost certain that im missing something fundamental here. can anyone please help with this? just run me through the necessary steps?
You're referencing ChangeAction by its unqualified name, so you have to make its namespace visible from your module:
using System.Data.Linq;
If the above gives an error, you probably also should add the System.Data.Linq assembly to your project's references.
Related
I spent a long time trying to get the ASP.NET MVC [HandleError] attribute to work in my websites. It seemed like a good idea to go with the solution offered by the framework, but I just couldn't get it to do anything useful. Then I tried writing my own attribute (mainly so that I could step in to the code with the debugger), but although my code seemed to be doing all the right things, after it executed the framework took over and did mysterious things. Finally I tried the MVC Contrib's [Rescue] attribute, which was better but I still couldn't get it to do what I wanted.
One problem is that exceptions thrown in code embedded in aspx / ascx pages get wrapped in HttpException's and WebHttpException's.
Another problem for me was that the system is very opaque. I was essentially poking inputs in to a black box with some desired outputs in mind, but with no idea (other than the documentation, which doesn't seem very accurate / thorough) what the relationship was between them.
So, what to do?
I went for Dynamic Proxies in Castle Windsor, using the code below, which tries to handle Database errors, for which I have a specific Exception (AccessDBException).
The _alreadyAttemptedToShowErrorPage is to stop infinite recursion in the case where the error page throws an Exception.
The GetAccessDBException(...) method finds the relevant exception anywhere in the Exception stack, for the case when there are problems in aspx / ascx code.
The code requires that there is a BaseController class that all controllers derive from. This class is used to add a CreateErrorView(...) method (being as the standard View(...) method is protected)
public class AccessDBExceptionHandlingDynamicProxy : IInterceptor
{
private bool _alreadyAttemptedToShowErrorPage;
public AccessDBExceptionHandlingDynamicProxy()
{
_alreadyAttemptedToShowErrorPage = false;
}
public void Intercept(IInvocation invocation)
{
Contract.Requires(invocation.Proxy is BaseController);
try
{
invocation.Proceed();
}
catch (HttpException e)
{
if (_alreadyAttemptedToShowErrorPage == true) throw e;
_alreadyAttemptedToShowErrorPage = true;
var dbException = GetAccessDBException(e);
if (dbException != null)
{
var baseController = (invocation.Proxy as BaseController);
var view = baseController.CreateErrorView("AccessDBException", new AccessDBExceptionViewModel(dbException));
baseController.Response.Clear();
baseController.Response.StatusCode = (int) HttpStatusCode.InternalServerError;
view.ExecuteResult(baseController.ControllerContext);
baseController.Response.End();
}
else
{
throw e;
}
}
}
private static AccessDBException GetAccessDBException(HttpException e)
{
AccessDBException dbException = null;
Exception current = e;
while (dbException == null && current != null)
{
if (current is AccessDBException) dbException = (current as AccessDBException);
current = current.InnerException;
}
return dbException;
}
}
I'm looking to add some background processing to my ASP.NET MVC 5 application, more specifically executing some long-ish (5-10 seconds) running tasks with HostingEnvironment.QueueBackgroundWorkItem. Now, the problem that I'm having is that code is running "out of band" and is not tied to the request any more - Autofac disposes of some of the injected dependencies.
Here is some of the code:
[HttpPost, ActionName("Execute")]
public ActionResult ExecutePost(Guid taskguid, FormCollection values)
{
if (taskguid == default(Guid))
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
var model = _taskListService.GetTaskByGuid(taskguid);
if (TryUpdateModel(model.TaskObject as MissingCrossReferenceTask))
{
model.TaskObject.DependencyContainer = _dependencyContainer;
model.TaskObject.TaskListId = model.Id;
HostingEnvironment.QueueBackgroundWorkItem(ct => ExecuteTask(ct, model));
return RedirectToAction("Index", "Dashboard");
}
return View(model);
}
In the code above DependencyContainer is an object that contains a number of dependencies that are injected by Autofac (EF Repositories and Services)
private void ExecuteTask(CancellationToken ct, TaskList model)
{
model.TaskObject.Execute();
}
Inside of that execute method of the MissingCrossReferenceTask (which is in a separate assembly from the ASP.NET MVC project:
public bool Execute()
{
long tableId = DependencyContainer.CrossReferenceService.GetCrossReferenceTable(TableName).Id;
string currentValue = DependencyContainer.CrossReferenceService.GetValue(FromValue, tableId);
...
}
The first line throws an exception: ObjectDisposedExcetion {"The ObjectContext instance has been disposed and can no longer be used for operations that require a connection."}
Now, I don't know the Autofac well enough to figure out the best way around this. Is it somehow possible to re-inject the reference directly in ExecuteTask method? If so - how?
I would extremely appreciate any help of this. It has been driving me insane for a few days now...
Thanks,
Nick Goloborodko
I guess submitting the question has forced me to look at the problem from a slightly different angle.
I think I have found a way around this (in other words - it now works as I'd like it to). I'm still not sure if this approach is the best in my situation or if there are any unseen problems with it - I would much appreciate any comments around this topic!
I have solved the issue in the following way:
private void ExecuteTask(CancellationToken ct, TaskList model)
{
MvcApplication app = this.HttpContext.ApplicationInstance as MvcApplication;
using (var container = app.ContainerProvider.ApplicationContainer.BeginLifetimeScope(WebLifetime.Application))
{
model.TaskObject.DependencyContainer = container.Resolve<DependencyContainer>();
model.TaskObject.Execute();
}
}
(adopted from a solution posted on this page: http://aboutcode.net/2010/11/01/start-background-tasks-from-mvc-actions-using-autofac.html)
Hope this may save a bit of time to someone else in the future!
I am trying to work through the example from Steve Sandersons SPA video.
http://channel9.msdn.com/Events/TechDays/Techdays-2012-the-Netherlands/2159
Much like the fellow in this question - Could not load type HttpControllerConfigurationAttribute after updating to Asp.Net MVC 4 RTM - My version does work with ApiController, but I need either DbDataController or LinqToEntitiesController, however during runtime both cause the exception below:
Could not load type 'System.Web.Http.Controllers.HttpControllerConfigurationAttribute' from
assembly 'System.Web.Http, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35'.
I'm not explicitly using HttpControllerConfigurationAttribute. Here is my code.
namespace MvcApplication5.Controllers
{
public class DataServiceController : DbDataController<MSEnterpriseEntities>
{
public IQueryable<MS_Substations> GetUtilities()
{
return DbContext.MS_Substations.OrderBy(x => x.SubId);
}
public void InsertUtility(MS_Substations utility) { InsertEntity(utility); }
public void DeleteUtility(MS_Substations utility) { DeleteEntity(utility); }
public void UpdateUtility(MS_Substations utility) { UpdateEntity(utility); }
}
}
I know HttpControllerConfigurationAttribute has been removed from System.Web.Http - I Don't know how to fix the problem though.
What exactly (for dummies version) do I need to do to fix this problem?
When I run following code:
public ActionResult Complete()
{
try
{
VeriTabanDataContext db = new VeriTabanDataContext();
db.Persons.InsertOnSubmit(_person);
db.SubmitChanges();
return View(_person);
}
catch (Exception ex)
{
return RedirectToAction("Error", ex);
}
}
I'm getting following Exception, on SubmitChanges();
"An attempt has been made to Attach or Add an entity that is not new, perhaps having been loaded from another DataContext. This is not supported."
Here "_person" object is taken from Session and is a good standing. Note: _person is a result of multistep wizard and this is the place where I add new Person object to the DB.
My Person table has 9 relations and it's not ok for me to add version column for each of them as is suggested by some geeks around
I've investigated this problem a lot and spend 2 days on it and still couldn't solve it. Some of the workarounds that other suggest don't solve my problem, and others seem to be just dirty workaround. Do you experts have a good solution for this problem, considering that Person class has many relations and also it isn't ok to add a column to the tables.
I also want to note that I've tried to use 'db.Persons.Attach(_person) ' and setting db.DeferredLoadingEnabled = false; THis time I'm not getting any Exception but data is NOT saved to DB
I create a class called applicationController which derives from Controller. Then i make all of my controller classes derive from this. The applicationController class has a constrcutor which creates a new instance of my repository (or datacontext in your instance) which is used throughout the application:
public class ApplicationController : Controller
{
private VeriTabanDataContext _datacontext;
public ApplicationController() : this(new VeriTabanDataContext())
{
}
public ApplicationController(VeriTabanDataContext datacontext)
{
_datacontext = datacontext;
}
Public VeriTabanDataContext DataContext
{
get { return _datacontext; }
}
}
Then you can use this in all of your controllers
public class MyController : ApplicationController
{
public ActionResult Complete()
{
DataContext.Persons.InsertOnSubmit(_person);
DataContext.SubmitChanges();
return View(_person);
}
}
Not on my PC with VS installed at the moment so not tested this code....
Hope this resolves the issue -Mark
Can you do the following:
var foundPerson = db.Person.FirstOrDefault( p => p.Id == _person.Id);
if(foundPerson == null)
{
db.InsertOnSubmit(_person);
}else{
Mapper.Map(_person,foundPerson);
}
db.SubmitChanges();
return View(_person);
Where I have used AutoMapper to map from one entity to another. To do this add the reference to AutoMapper to your project and in your start up code for the application you will need to configure your mappings, for the above to work you would need:
Mapper.CreateMap<Person, Person>().ForMember(src => src.Id, opt => opt.Ignore());
I'm trying to implement my own GenericIdentity implementation but keep receiving the following error when it attempts to load the views (I'm using asp.net MVC):
System.Runtime.Serialization.SerializationException was unhandled
by user code Message="Type is not resolved for member
'OpenIDExtendedIdentity,Training.Web, Version=1.0.0.0,
Culture=neutral, PublicKeyToken=null'."
Source="WebDev.WebHost"
I've ended up with the following class:
[Serializable]
public class OpenIDExtendedIdentity : GenericIdentity {
private string _nickName;
private int _userId;
public OpenIDExtendedIdentity(String name, string nickName, int userId)
: base(name, "OpenID") {
_nickName = nickName;
_userId = userId;
}
public string NickName {
get { return _nickName; }
}
public int UserID {
get { return _userId; }
}
}
In my Global.asax I read a cookie's serialized value into a memory stream and then use that to create my OpenIDExtendedIdentity object. I ended up with this attempt at a solution after countless tries of various sorts. It works correctly up until the point where it attempts to render the views.
What I'm essentially attempting to achieve is the ability to do the following (While using the default Role manager from asp.net):
User.Identity.UserID
User.Identity.NickName
... etc.
I've listed some of the sources I've read in my attempt to get this resolved. Some people have reported a Cassini error, but it seems like others have had success implementing this type of custom functionality - thus a boggling of my mind.
http://forums.asp.net/p/32497/161775.aspx
http://ondotnet.com/pub/a/dotnet/2004/02/02/effectiveformsauth.html
http://social.msdn.microsoft.com/Forums/en-US/netfxremoting/thread/e6767ae2-dfbf-445b-9139-93735f1a0f72
I'm not sure if this is exactly the same issue, but I've run into the same issue when trying to create my own identity implementation.
This blog solved my problem.
It seems that the problem is there's an issue with identity serialization in Cassini, but you can get around it by deriving your class from MarshalByRefObject:
[Serializable]
public class MyUser : MarshalByRefObject, IIdentity
{
public int UserId ...
You can't inherit from GenericIdentity then, of course, but you can still implement the IIdentity interface that GenericIdentity implements, so you can use the thing in most places that expect an IIdentity at least.
It seems to be a limitation or a bug of the VisualStudio (Web Development Server), when I used the IIS Express in VS2012 or the full IIS config, the problem was fixed. Like suggested here: https://stackoverflow.com/a/1287129/926064
Solution from "baggadonuts" at This post solved my problem. Copied code below.
[Serializable]
public class StubIdentity : IIdentity, ISerializable
public void GetObjectData(SerializationInfo info, StreamingContext context)
{
if (context.State == StreamingContextStates.CrossAppDomain)
{
GenericIdentity gIdent = new GenericIdentity(this.Name, this.AuthenticationType);
info.SetType(gIdent.GetType());
System.Reflection.MemberInfo[] serializableMembers;
object[] serializableValues;
serializableMembers = FormatterServices.GetSerializableMembers(gIdent.GetType());
serializableValues = FormatterServices.GetObjectData(gIdent, serializableMembers);
for (int i = 0; i < serializableMembers.Length; i++)
{
info.AddValue(serializableMembers[i].Name, serializableValues[i]);
}
}
else
{
throw new InvalidOperationException("Serialization not supported");
}
}