Register a SA Forums Account here!
JOINING THE SA FORUMS WILL REMOVE THIS BIG AD, THE ANNOYING UNDERLINED ADS, AND STUPID INTERSTITIAL ADS!!!

You can: log in, read the tech support FAQ, or request your lost password. This dumb message (and those ads) will appear on every screen until you register! Get rid of this crap by registering your own SA Forums Account and joining roughly 150,000 Goons, for the one-time price of $9.95! We charge money because it costs us money per month for bills, and since we don't believe in showing ads to our users, we try to make the money back through forum registrations.
 
  • Post
  • Reply
Bognar
Aug 4, 2011

I am the queen of France
Hot Rope Guy
React isn't usually the best choice for pure CRUD applications. I generally break it out when something has a lot of UI interaction, constant updates, or complex rules. For example, I recently needed to build a page in a website that had "Excel-like" editing of a big table, with click and drag, arrow keys to move between cells, validation of cells, etc. With React, I had it done in an afternoon and the code was pretty clean and performant. I don't even want to think about what that would look like with just jQuery (for example).

Adbot
ADBOT LOVES YOU

kitten emergency
Jan 13, 2008

get meow this wack-ass crystal prison

Uziel posted:

Wait, are you me from the future? This is the exact same scenario I'm in: internal tool, two developers, me pushing for cutting edge technology, not a lot of time to work on it due to current version being unmaintainable horror show, etc.

Thanks for the write up, that's helpful. I saw that you mentioned you used jquery rather than flux. Is it too late for that now? Did you use reactjs.net (http://reactjs.net/)?

I didn't use reactjs.net because i'm not really doing any of my react stuff intermingled with cshtml or razor. It's all separate files.

As for React vs. Knockout vs. whatever, React really shines when you're having to do a lot of updates or you're doing DOM manipulation. If you've got a static page or a form that you can hook up to your data bindings and hit save and that's fine, then cool. In our case, views need to update dynamically based on changing information on the server and I didn't really find anything that matched the speed of React (shadow DOM manipulation) or its ease-of-use.

LiterallyAnything
Jul 11, 2008

by vyelkin
Can anyone answer this dumb question for me please? I have a grid layout with rows and columns and now I want to add two more rows. Each method I've tried results in the other rows getting resized, or the elements already inside the grid being moved out of place. I just want to add on to the rows and make the whole grid larger. What's the best way to go about this?


Edit- I think I'm realizing that the real solution here is to create your grid with the proper amount of rows and columns BEFORE adding your content. drat it. If that's the case how do people edit their layouts after the fact when needed? Do they go back and resize every element? That can't be it, I've got to be doing something wrong.

Edit edit- Yeah I definitely did that wrong. Trying to create my first "proper" WPF application and not use absolute positioning.

LiterallyAnything fucked around with this message at 01:08 on Nov 12, 2015

EssOEss
Oct 23, 2006
128-bit approved
There is a basic choice you need to make with each element: is this element sized by its container or does this element size itself?

If the element is sized by its container, don't set any size values on the element (i.e. set it to stretch - most things default to stretch, though not all) and just size the container by e.g. adjusting the grid row/column sizes.

If the element sizes itself, well, just write what size it needs to be! If you get it wrong and things don't fit well then yes, you will have much resizing to do later.

It can be okay to mix the two approaches, as long as you have a clear strategy for the sizing of each and every element. Generally, I find letting elements just stretch to the container is the easiest to start with - later when doing your 3rd layout adjusting pass, you can start applying explicit sizing to outstanding elements to make it visually more appealing.

(You'll usually want to apply a margin to the element, regardless of which way you go, to space things out.)


To be specific to your grid scenario - if you really want to make a grid and add more rows to it later without affecting the existing rows, ensure that all existing rows have fixed size (no star-sizing like 3*) and that you have an extra row for the empty space with a star size. Any new rows will, in this manner, take space away from the extra row, instead of modifying the existing ones.

EssOEss fucked around with this message at 08:11 on Nov 12, 2015

Gul Banana
Nov 28, 2003

uncurable mlady posted:

I didn't use reactjs.net because i'm not really doing any of my react stuff intermingled with cshtml or razor. It's all separate files.

Did you manage to get any server-side rendering going?

LiterallyAnything
Jul 11, 2008

by vyelkin

EssOEss posted:

There is a basic choice you need to make with each element: is this element sized by its container or does this element size itself?

If the element is sized by its container, don't set any size values on the element (i.e. set it to stretch - most things default to stretch, though not all) and just size the container by e.g. adjusting the grid row/column sizes.

If the element sizes itself, well, just write what size it needs to be! If you get it wrong and things don't fit well then yes, you will have much resizing to do later.

It can be okay to mix the two approaches, as long as you have a clear strategy for the sizing of each and every element. Generally, I find letting elements just stretch to the container is the easiest to start with - later when doing your 3rd layout adjusting pass, you can start applying explicit sizing to outstanding elements to make it visually more appealing.

(You'll usually want to apply a margin to the element, regardless of which way you go, to space things out.)


To be specific to your grid scenario - if you really want to make a grid and add more rows to it later without affecting the existing rows, ensure that all existing rows have fixed size (no star-sizing like 3*) and that you have an extra row for the empty space with a star size. Any new rows will, in this manner, take space away from the extra row, instead of modifying the existing ones.

Excellent. Thanks so much for the advice!

epswing
Nov 4, 2003

Soiled Meat
I have a WebAPI controller, with a method to return a Ticket, decorated with an Authorize attribute, which specifies a required Role.

C# code:
public class MyApiController : ApiController
{
    [HttpGet]
    [Authorize(Roles = "ViewTickets")]
    public Ticket GetTicket(int id)
    {
        return ticketService.GetTicket(id);
    }
}
To make a request from a client application, I first log in by POSTing to http://thesite/Token as a x-www-form-urlencoded containing grant_type=password, username=blah, password=blah. I get back, among other things, an access token. Here's what the response looks like:

pre:
{
    "access_token": "jfd2zJtdC...",
    "token_type": "bearer",
    "expires_in": 1209599,
    "userName": "blah",
    ".issued": "Thu, 12 Nov 2015 17:58:37 GMT",
    ".expires": "Thu, 26 Nov 2015 17:58:37 GMT"
}
I now have a token I can use to hit the WebAPI.

When I make a request to http://thesite/api/Tickets/1000 to pull down a ticket, I stuff the token in the header Authorization=Bearer jfd2zJtdC...

This all works fine. If the user making the request doesn't have the ViewTickets role, the response is a 401, as expected. And if the user does have the ViewTickets role, I get back some JSON, also as expected.

The trouble is, if a user's roles are modified after receiving a token, the change is not reflected whenever the Authorize attribute is hit. In other words, if a user had the ViewTickets role, logs in, receives a token, then an administrator removes that user's ViewTickets role, the user can still access functions which require the ViewTickets role.

How can I update (or perhaps invalidate?) the token when changes are made to the roles users are assigned?

Edit: Even if I remove the user from all roles, and delete the user, requests using a previously accepted token still work. When issued a token, is ASP.NET basically saying "ok user, you have these roles right now, and you will continue to have them until this token expires"?

epswing fucked around with this message at 22:32 on Nov 12, 2015

Bognar
Aug 4, 2011

I am the queen of France
Hot Rope Guy

epalm posted:

The trouble is, if a user's roles are modified after receiving a token, the change is not reflected whenever the Authorize attribute is hit. In other words, if a user had the ViewTickets role, logs in, receives a token, then an administrator removes that user's ViewTickets role, the user can still access functions which require the ViewTickets role.

How can I update (or perhaps invalidate?) the token when changes are made to the roles users are assigned?

The token stores identity information (username, id) as well as all the roles that the user had when logging in. It does this so it doesn't have to hit the database for user info every time you need to check permissions, but it has the downside of not changing when roles information changes.

If you're okay with hitting the database every time, I would build a custom Authorize attribute by inheriting from AuthorizeAttribute and overriding the method that validates the user (can't remember what the name is off the top of my head). If you don't want to hit the database on every role check, you could still populate a cache of when the roles were most recently changed and only hit the database if the roles update date for that user is later than the ticket date.

EDIT: For example,

C# code:
public class CustomAuthorizeAttribute : AuthorizeAttribute
{
    public override void OnAuthorization(AuthorizationContext filterContext)
    {
        if (!filterContext.HttpContext.Request.IsAuthenticated)
        {
            // Redirect to login page
            filterContext.Result = Redirect("Login", "Index")'
            return;
        }

        var roles = GetRolesFromDb();
        if (Roles.Any(r => roles.Contains(r)))
            return;
        else
            filterContext.Result = Redirect("Error", "AccessDenied");
    }

    private RedirectToRouteResult Redirect(string controller, string action, string area = "")
    {
        return new RedirectToRouteResult(new RouteValueDictionary(new
        {
            controller,
            action,
            area,
        });
    }
}

Bognar fucked around with this message at 23:09 on Nov 12, 2015

epswing
Nov 4, 2003

Soiled Meat

Bognar posted:

The token stores identity information (username, id) as well as all the roles that the user had when logging in. It does this so it doesn't have to hit the database for user info every time you need to check permissions, but it has the downside of not changing when roles information changes.

This was just starting to dawn on me, after seeing a deleted user still had access. I've already written the custom attribute (which extends AuthorizeAttribute), seems to work well. In the future, and if necessary, I'll cache the values outside the DB.

Thanks!

Edit: Mine looks like this, please critique! Note that it subclasses the WebAPI AuthorizeAttribute, not the MVC one.

C# code:
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false)]
public class AuthorizeExAttribute : System.Web.Http.AuthorizeAttribute
{
    public string[] RolesArray { get; set; }

    public AuthorizeExAttribute(params string[] roles)
    {
        Roles = string.Join(",", roles);
        RolesArray = roles;
    }

    protected override bool IsAuthorized(HttpActionContext actionContext)
    {
        var userName = actionContext.RequestContext.Principal.Identity.Name;

        if (userName == null)
            return false;

        using (var context = new UserContext())
        {
            var userStore = new UserStore<ApplicationUser>(context);
            var userManager = new UserManager<ApplicationUser>(userStore);
            var user = userManager.FindByName(userName);

            if (user == null)
                return false;

            foreach (var role in RolesArray)
                if (!userManager.IsInRole(user.Id, role))
                    return false;

            return true;
        }
    }
}
C# code:
public class MyApiController : ApiController
{
    [HttpGet]
    [AuthorizeEx("ViewTickets", "EditTickets")]
    public Ticket GetTicket(int id)
    {
        return blah;
    }
}

epswing fucked around with this message at 23:35 on Nov 12, 2015

putin is a cunt
Apr 5, 2007

BOY DO I SURE ENJOY TRASH. THERE'S NOTHING MORE I LOVE THAN TO SIT DOWN IN FRONT OF THE BIG SCREEN AND EAT A BIIIIG STEAMY BOWL OF SHIT. WARNER BROS CAN COME OVER TO MY HOUSE AND ASSFUCK MY MOM WHILE I WATCH AND I WOULD CERTIFY IT FRESH, NO QUESTION
Cross-posting here from StackOverflow because I'm completely stuck on this and it's driving me up the loving wall.

I need to allow users to download files from our server, and I'd like to serve these files via an ASP.NET MVC 5 controller action. My action looks like this:

code:
    public FileContentResult Download(int fileId)
    {
        var myContent = GetContentForFile(fileId);
        var myFileMeta = GetFileMeta(fileId);

        if (myContent == null || myFileMeta == null)
            throw new FriendlyException("The file or its associated data could not be found.");

        return File(myContent.Content, myContent.MediaType, myFileMeta.FileName);
    }
The above is as simple as I could get it, it works fine on PC and iPhone, but not on Android. Using Fiddler, I can see that I'm getting the following response headers when I try to download one of my files - in this case a JPG file called "1447114384146-643143584.jpg":

code:
    HTTP/1.1 200 OK
    Cache-Control: private, s-maxage=0
    Content-Type: image/jpeg
    Server: Microsoft-IIS/8.5
    X-AspNetMvc-Version: 5.2
    Content-Disposition: attachment; filename=1447114384146-643143584.jpg
    X-AspNet-Version: 4.0.30319
    X-Powered-By: ASP.NET
    Date: Thu, 12 Nov 2015 23:09:00 GMT
    Content-Length: 1682868
To clarify, when I attempt to download any file via that controller action, using Android, I get a toast notification telling me "Download started", but then the download sits in the queue for a while on 0% before eventually just changing to "Failed". Accessing the same URL on iPhone, PC (Chrome, Firefox and IE) or even via Fiddler all works fine.

What I've tried

I've tried all manner of things that people have suggested in similar questions, most of which are to do with the content-disposition header or the content-type header. I've tried forcing the content-type header to application/octet-stream for every file, I've tried sending the correct content-type header for the particular file. I've tried manually sending the content-disposition header. I've tried forcing the filename extension to uppercase.

None of the above has worked, in fact none of them have had any impact at all on the problem, for better OR worse. I'm amazed that this is so hard - I feel like I must be missing something obvious?

After reading this blog entry: http://www.digiblog.de/2011/04/android-and-the-download-file-headers/ I tried following the advice and set my headers exactly as suggested:

code:
    HTTP/1.1 200 OK
    Cache-Control: private, s-maxage=0
    Content-Type: application/octet-stream
    Server: Microsoft-IIS/8.5
    X-AspNetMvc-Version: 5.2
    Content-Disposition: attachment; filename="1447114384146-643143584.JPG"
    X-AspNet-Version: 4.0.30319
    X-Powered-By: ASP.NET
    Date: Thu, 12 Nov 2015 23:42:18 GMT
    Content-Length: 1682868
Again, this had no impact on the problem at all.

Additional information

Browser: latest Chrome on Android
OS: Android 5.1 (also occurs for a coworker on their Android phone which is at an earlier Android version (not sure which specifically), so I don't think this is tied to a specific Android version).

Update: I have been able to test on a Marshmallow (Android v6.0) device and the download works. It seems to be a pre-Marshmallow issue.

putin is a cunt fucked around with this message at 02:05 on Nov 13, 2015

Gul Banana
Nov 28, 2003

have you checked whether the android device can download from other websites?

biznatchio
Mar 31, 2001


Buglord
The first thing I'd do to debug that sort of problem is to stick a proxy between the device and the service and see exactly what's happening on the wire.

Bognar
Aug 4, 2011

I am the queen of France
Hot Rope Guy

epalm posted:

Edit: Mine looks like this, please critique! Note that it subclasses the WebAPI AuthorizeAttribute, not the MVC one.

You're checking that the user has ALL roles listed, while the default implementation checks for ANY of the roles listed. Also, setting the base Roles property in the constructor isn't necessary since you're not using it in your implementation.

epswing
Nov 4, 2003

Soiled Meat

Bognar posted:

You're checking that the user has ALL roles listed, while the default implementation checks for ANY of the roles listed. Also, setting the base Roles property in the constructor isn't necessary since you're not using it in your implementation.

Ah weird, I assumed the default behavior was ALL. As in, "to execute this function, you must be a (1) Senior (2) Manager, at (3) Head Office" is how it makes sense in my head. Good to know the default is ANY.

I populated Roles in case the superclass needs it for some reason I haven't thought of. I suppose I should be able to pull up the AuthorizeAttribute source code these days and confirm that myself, though.

Thanks!

putin is a cunt
Apr 5, 2007

BOY DO I SURE ENJOY TRASH. THERE'S NOTHING MORE I LOVE THAN TO SIT DOWN IN FRONT OF THE BIG SCREEN AND EAT A BIIIIG STEAMY BOWL OF SHIT. WARNER BROS CAN COME OVER TO MY HOUSE AND ASSFUCK MY MOM WHILE I WATCH AND I WOULD CERTIFY IT FRESH, NO QUESTION

Gul Banana posted:

have you checked whether the android device can download from other websites?

biznatchio posted:

The first thing I'd do to debug that sort of problem is to stick a proxy between the device and the service and see exactly what's happening on the wire.

I did both of these things with no answers provided, however I finally figured out the problem: Android does not like underscores in domain names, and our local domain has an underscore in it. Thanks infrastructure team!

Mr Shiny Pants
Nov 12, 2012

The Wizard of Poz posted:

I did both of these things with no answers provided, however I finally figured out the problem: Android does not like underscores in domain names, and our local domain has an underscore in it. Thanks infrastructure team!

Thanks Android more like, good that they fixed it in newer versions though.

putin is a cunt
Apr 5, 2007

BOY DO I SURE ENJOY TRASH. THERE'S NOTHING MORE I LOVE THAN TO SIT DOWN IN FRONT OF THE BIG SCREEN AND EAT A BIIIIG STEAMY BOWL OF SHIT. WARNER BROS CAN COME OVER TO MY HOUSE AND ASSFUCK MY MOM WHILE I WATCH AND I WOULD CERTIFY IT FRESH, NO QUESTION

Mr Shiny Pants posted:

Thanks Android more like, good that they fixed it in newer versions though.

True, although technically they were just following the spec. But yeah I'm also glad they fixed it because its stupid as gently caress.

Gul Banana
Nov 28, 2003

friend who works at a closer-microsoft-partner-than-us consultancy was asking me the other day how come we weren't building touch interfaces for any of our software. i told him that none of our (government, business) clients have touch systems or plans to acquire any, and he was all "yeah, us too". so i asked how come they DO do 'modern' uis (actually a clever WPF skin they have to look like metro) and it turns out microsoft gave them some sort of Large Incentive. i wonder if that strategy will work out...

EssOEss
Oct 23, 2006
128-bit approved
Microsoft shovels out fat wads of cash all the time to get app developers with sufficient market visibility to use their new fancy technologies. I remember it was pretty big with Silverlight. Something like 50% of a suitable project's budget would come straight from Microsoft. It's a marketing move for sure but everyone was happy with the arrangement, so I can't complain. When you're dealing with a large enough scale it can be OK if 90% of your efforts miss the mark, as the 10% can still bring enough benefit to make everything worthwhile.

Ika
Dec 30, 2004
Pure insanity

I'm using mixed mode C++ to call some methods on a .NET assembly, and can'tfigure out an easier method of doing the following:

code:
bool foo::dostuff(Object ^blah)
{
    msclr::auto_gcroot<BaseClass> temp = blah->GetContainer()
    msclr::auto_gcroot<DerivedClass> temp2 = safe_cast<DerivedClass>( temp )
    if (temp2.get() == nullptr)
        return false;
    this->container = std::move( temp2 );
    temp.release(); // WHY!?
}
Without the release, the object is disposed + deleted even though it is being set in the class's member variable, when the temp variable runs out of scope. Is there some better way of doing this without leaking the object if the safe_cast fails? I would expect the assignment after the cast to add another reference to the object, but it doesn't.

Ika fucked around with this message at 18:20 on Nov 17, 2015

epswing
Nov 4, 2003

Soiled Meat
Whoops. Nevermind.

epswing fucked around with this message at 18:49 on Nov 17, 2015

raminasi
Jan 25, 2005

a last drink with no ice

Ika posted:

I'm using mixed mode C++ to call some methods on a .NET assembly, and can'tfigure out an easier method of doing the following:

code:
bool foo::dostuff(Object ^blah)
{
    msclr::auto_gcroot<BaseClass> temp = blah->GetContainer()
    msclr::auto_gcroot<DerivedClass> temp2 = safe_cast<DerivedClass>( temp )
    if (temp2.get() == nullptr)
        return false;
    this->container = std::move( temp2 );
    temp.release(); // WHY!?
}
Without the release, the object is disposed + deleted even though it is being set in the class's member variable, when the temp variable runs out of scope. Is there some better way of doing this without leaking the object if the safe_cast fails? I would expect the assignment after the cast to add another reference to the object, but it doesn't.

Why are you using auto_gcroots instead of normal handles?

e: To elaborate a bit more, what you're doing is analogous to this:
C# code:
DerivedClass temp2;
using (BaseClass temp = blah.GetContainer())
{
    temp2 = (DerivedClass)temp;
}
// temp is now Disposed, so temp2 can't be used for anything
(Sidenote - safe_cast throws if it fails, so that null check isn't checking for a failed cast.)

To avoid this, you'd want to remove the implicit using block that all non-handles are surrounded with in C++/CLI. I was originally going to suggest that you replace the auto_gcroot with a normal handle, but it's not wrapping a handle, so that wouldn't solve the problem either.

raminasi fucked around with this message at 19:19 on Nov 17, 2015

Ika
Dec 30, 2004
Pure insanity

The objects in the auto_gcroot pointers are handles to classes retrieved from an external API, I must have killed the ^ in the pointer declaration when replacing the types to simplify.

I thought normal handles don't get cleaned up properly without auto_gcroot, which would mean if the cast throws I would leak the base version of the object. (Or rather, it wouldn't be finalized properly).

So I thought I couldn't do something like:

msclr::auto_gcroot<DerivedClass^> temp(safe_cast<DerivedClass^>( blah->GetContainer() );

because if that throws, then the object that was returned is leaked.

Ika fucked around with this message at 20:30 on Nov 17, 2015

raminasi
Jan 25, 2005

a last drink with no ice

Ika posted:

The objects in the auto_gcroot pointers are handles to classes retrieved from an external API, I must have killed the ^ in the pointer declaration when replacing the types to simplify.

I thought normal handles don't get cleaned up properly without auto_gcroot, which would mean if the cast throws I would leak the base version of the object. (Or rather, it wouldn't be finalized properly).

So I thought I couldn't do something like:

msclr::auto_gcroot<DerivedClass^> temp(safe_cast<DerivedClass^>( blah->GetContainer() );

because if that throws, then the object that was returned is leaked.

Nope, normal handles are cleaned up just fine. That's the whole point of them - they're essentially identical to C# references. In general, I've found that treating C++/CLI as C# with funny syntax makes it more intuitive than treating it as C++ with extensions. auto_gcroot is necessary if you need to store a handle inside a native C++/CLI class. I'd actually never heard of them before, because that's such an uncommon use case. (I can't actually think of any reason to create a native C++/CLI class at all.) And you can basically think of it as a syntactic problem (native classes don't understand ^) - it's not because you need to specifically manage handle lifetime in the general case. They Dispose their wrapped objects in their destructors because that's how the C++ half of C++/CLI works.

So let's get back to your original question. First, I'm assuming that blah->GetContainer() is creating a new object, because otherwise trying to Dispose it in calling code is, at best, an awful, awful code smell. (And if it is creating a new object, it doesn't have a great name.) What happens in your simple proposal if the downcast fails? Well, nothing will ever Dispose the returned BaseClass, but it will get finalized and collected properly, because it's a managed object like any other. (C++/CLI requires that you be perfectly clear on the difference between disposal, finalization, and collection, and how its different syntactic constructs map to each of them.)

This may not be the end of the world, depending on why exactly BaseClass is IDisposable. But if you want to make sure that Dispose is called if GetContainer returns the wrong type, you can try to leverage C++/CLI scoping syntax, or gc_autoroot (which is basically what you were doing before), but if it were me, I'd just do it myself:
code:
void foo::dostuff(Object ^blah)
{
    BaseClass ^baseContainer = nullptr;
    DerivedClass ^derivedContainer = nullptr;
    try
    {
        baseContainer = blah->GetContainer();
        derivedContainer = safe_cast<DerivedClass^>(container);
        this->container = msclr::auto_gcroot<DerivedClass^>(derivedContainer);
    }
    finally
    {
        if (baseContainer != nullptr && derivedContainer == nullptr)
        {
            delete baseContainer;
        }
    }
}
(You could also swallow exceptions and just return false.)

Of course, if BaseClass isn't IDisposable and you just conflated disposal with collection, this is all unnecessary anyway.

raminasi fucked around with this message at 21:47 on Nov 17, 2015

Ika
Dec 30, 2004
Pure insanity

I'm fairly sure the base class is disposable, since its an interface pointer.

As to why you would need C++ / CLI, this is what we are doing. (And this might the completely wrong approach, but all of us are C++ / COM coders and haven't really done anything with .NET)

We are trying to use a .NET API in one of our com objects. We can't change the compile settings of class A to support mixed C++/.NET and using this structure we could ensure that class A still compiles fine and can indirectly use the .NET functions. What we have done is

Class A is pure C++ / COM object, and contains a pointer to a class B.
Class B is pure virtual base class.
Class BImpl is mixed mode c++ / CLI class, derives from B, and stores this pointer to the api via auto_gcroot, and implements all the functionality which needs the calls to the .NET class. BImpl also connects to the .NET events and forwards them to A.



E: Doing it yourself is nice when it is a simple example, but when you have to do this several times per function it starts to get tedious.

E2: I'm starting to think I should create a pure .NET class to wrap all the .NET functionality, as well as garbage collection etc, and use that in BImpl.

Ika fucked around with this message at 22:00 on Nov 17, 2015

raminasi
Jan 25, 2005

a last drink with no ice

Ika posted:

I'm fairly sure the base class is disposable, since its an interface pointer.

As to why you would need C++ / CLI, this is what we are doing. (And this might the completely wrong approach, but all of us are C++ / COM coders and haven't really done anything with .NET)

We are trying to use a .NET API in one of our com objects. We can't change the compile settings of class A to support mixed C++/.NET and using this structure we could ensure that class A still compiles fine and can indirectly use the .NET functions. What we have done is

Class A is pure C++ / COM object, and contains a pointer to a class B.
Class B is pure virtual base class.
Class BImpl is mixed mode c++ / CLI class, derives from B, and stores this pointer to the api via auto_gcroot, and implements all the functionality which needs the calls to the .NET class. BImpl also connects to the .NET events and forwards them to A.



E: Doing it yourself is nice when it is a simple example, but when you have to do this several times per function it starts to get tedious.

Oh, you guys aren't coming from a .NET background. This all makes a lot more sense.

So the first thing to check here is whether your API object is IDisposable or not. IDisposable is a specific .NET interface that indicates that a class would like to deterministically release some of its resources. If your API object does not implement IDisposable, your life just got a whole lot easier, because msclr::auto_gcroot<DerivedClass^> temp(safe_cast<DerivedClass^>( blah->GetContainer() ); will do exactly what you want without any leaks. (However, if you don't catch InvalidCastExceptions entirely inside your C++/CLI code, they'll bubble into your native code, which will probably not end well. Consider using dynamic_cast instead of safe_cast, which just returns null if there's a problem.)

If it does implement IDisposable, and it's a problem if objects are not properly disposed, you'll have to explicitly do the disposal. If you have to do it a zillion times you could just make yourself a little wrapper:
code:
DerivedClass^ cast_or_dispose(BaseClass ^baseClass)
{
    DerivedClass ^derived = dynamic_cast<BaseClass^>(baseClass);
    if (derived == nullptr)
    {
        delete baseClass;
    }
    return derived;
}
("The uncommon use case" I was referring to was a C++/CLI native class, as opposed to a C++/CLI managed class. However, inheriting from a pure C++ abstract base class is one of the cases that makes sense to do it. It just hadn't occurred to me.)

Ika
Dec 30, 2004
Pure insanity

sounds good, thanks for the help.

Luigi Thirty
Apr 30, 2006

Emergency confection port.

I'm bad at WPF. I have a byte array containing 8 bytes of image data (so an 8x8 1bpp image) that I want to display as a 64x64 Image on a window. I've been trying to use that WriteableBitmapEx library to load the image data into a WriteableBitmap and bind the Image to it but it's documented poorly and I can't work out how to do that.

To make sure it works, I bound the 64x64 WPF image to a 64x64 96dpi WriteableBitmap and when I do .Clear(Colors.Black) on it, only the right 1/4 of the image is cleared to the right color. I'm really confused.

Mr Shiny Pants
Nov 12, 2012

Luigi Thirty posted:

I'm bad at WPF. I have a byte array containing 8 bytes of image data (so an 8x8 1bpp image) that I want to display as a 64x64 Image on a window. I've been trying to use that WriteableBitmapEx library to load the image data into a WriteableBitmap and bind the Image to it but it's documented poorly and I can't work out how to do that.

To make sure it works, I bound the 64x64 WPF image to a 64x64 96dpi WriteableBitmap and when I do .Clear(Colors.Black) on it, only the right 1/4 of the image is cleared to the right color. I'm really confused.

How do you bind the image?

If you just bind it in Xaml and stretch it?

Kekekela
Oct 28, 2004

Gul Banana posted:

friend who works at a closer-microsoft-partner-than-us consultancy was asking me the other day how come we weren't building touch interfaces for any of our software. i told him that none of our (government, business) clients have touch systems or plans to acquire any, and he was all "yeah, us too". so i asked how come they DO do 'modern' uis (actually a clever WPF skin they have to look like metro) and it turns out microsoft gave them some sort of Large Incentive. i wonder if that strategy will work out...
This has always been their playbook. I worked at Extreme Logic back when BizTalk was first being introduced and the turdish v1 of that is what we were tasked with coming up with apps to demo as part of our most recent MSFT agreement.

Gul Banana
Nov 28, 2003

interesting. it could end up effective in this instance, since the idea is probably that everyone will have win10 *eventually*, at which point there are these random apps all ready for it.

Calidus
Oct 31, 2011

Stand back I'm going to try science!
On the topic of windows 10, is it safe to do .net 4 development on a windows 10 machine? I would really like to upgrade my work machine from 7 but I am kinda nervous windows 10 might jack up my development environment.

Bognar
Aug 4, 2011

I am the queen of France
Hot Rope Guy

Calidus posted:

On the topic of windows 10, is it safe to do .net 4 development on a windows 10 machine? I would really like to upgrade my work machine from 7 but I am kinda nervous windows 10 might jack up my development environment.

Nothing wrong with it that I know of. We have a few projects on 4.0 that have yet to be upgraded and I've been using Win10 since it released without issues.

No Safe Word
Feb 26, 2005

Windows 10 is completely fine for .NET 4.x development, we have several guys at work who have updated their machines and there's been zero issues.

xgalaxy
Jan 27, 2004
i write code
Hell. I'm doing .NET 3.5 development and it works fine.

wilderthanmild
Jun 21, 2010

Posting shit




Grimey Drawer
That put my fears aside then. I'm gonna update the OS on my laptop later today then. I was terrified of updating it, it breaking something for me development wise, and having to use only my desktop for programming.

Luigi Thirty
Apr 30, 2006

Emergency confection port.

Mr Shiny Pants posted:

How do you bind the image?

If you just bind it in Xaml and stretch it?

I'm not even trying to bind the actual image now, just get the drat thing to work right at all. Here's the Image on my WPF window. TestCharacter is a WriteableBitmap property which is not initialized at start time.

code:
<Image x:Name="imgTestCharacter" Source="{Binding Path=TestCharacter}" HorizontalAlignment="Left" Height="64" Margin="215,39,0,0" VerticalAlignment="Top" Width="64" Stretch="None"/>
And I press a button that initializes it and tries to clear it to black:

code:
vm.TestCharacter = new WriteableBitmap(64, 64, 96, 96, PixelFormats.BlackWhite, null);
vm.TestCharacter.Clear(Colors.Black);
and I get an access violation on .Clear().

EssOEss
Oct 23, 2006
128-bit approved
I believe you have to surround any touching of the WriteableBitmap with a .Lock() and .Unlock() pair, to properly synchronize everything.

Luigi Thirty
Apr 30, 2006

Emergency confection port.

EssOEss posted:

I believe you have to surround any touching of the WriteableBitmap with a .Lock() and .Unlock() pair, to properly synchronize everything.

I got an access violation still. I changed it to just SetPixel() but the results are wrong. Starting with a black image, this code:

code:
            vm.TestCharacter = new WriteableBitmap(64, 64, 96, 96, PixelFormats.BlackWhite, null);
            vm.TestCharacter.Lock();
            vm.TestCharacter.SetPixel(0, 1, Colors.White);
            vm.TestCharacter.Unlock();
gives me this image (minus the border). Shouldn't it be touching one pixel and not... many pixels?

Adbot
ADBOT LOVES YOU

Uziel
Jun 28, 2004

Ask me about losing 200lbs, and becoming the Viking God of W&W.
ASP.NET 5 is now RC1! Thank god as I started a new project just yesterday using beta8 and was running into weird issues.

http://blogs.msdn.com/b/dotnet/archive/2015/11/18/announcing-net-core-and-asp-net-5-rc.aspx

  • 1
  • 2
  • 3
  • 4
  • 5
  • Post
  • Reply